package admin

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"github.com/spf13/cast"
	"github.com/xuri/excelize/v2"
	"math"
	"outsourced-projects/pkg/communal"
	"outsourced-projects/pkg/utils"
	"outsourced-projects/service"
	"sort"
	"strings"
	"time"
)

type Clockin struct {
	service.Base
}

func (clockin Clockin) StatisticsList(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), cast.ToInt(jsondata["page_size"]))
	//limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), 10)
	orderstr := " order by a.`userid` desc"

	wheresql := strings.Builder{}

	if cast.ToString(jsondata["staff"]) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(jsondata["staff"])+"%"))
	}
	if cast.ToString(jsondata["department"]) != "" {
		//wheresql.WriteString(fmt.Sprintf(" and a.`main_department` = %s", cast.ToString(jsondata["department"])))
		relationship, err := db.QueryString(fmt.Sprintf("select relationship from department where id = %s limit 1", cast.ToString(jsondata["department"])))
		if err != nil {
			service.ReturnJson(c, 500, err.Error(), gin.H{})
			return
		}
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", relationship[0]["relationship"]+"%"))
	} else {
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-79%"))
	}

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position` from `staff` as a left join department b on a.main_department = b.id where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	countsql := fmt.Sprintf("select count(*) as total from `staff` as a left join department b on a.main_department = b.id where 1=1 %s", wheresql.String())
	countdata, err := db.QueryString(countsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinMonthdataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckinMonthdata := &ReqCheckinGetcheckinMonthdataStruct{
		Starttime:  cast.ToInt(jsondata["starttime"]),
		Endtime:    cast.ToInt(jsondata["endtime"]) + 86400,
		Useridlist: usermap,
	}
	b, err := json.Marshal(&ReqCheckinGetcheckinMonthdata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas, err := utils.CheckinGetcheckinMonthdata(b)

	//fmt.Println(datas)

	for _, v := range datas.Datas {
		for kk, vv := range listdata {
			if v.BaseInfo.Acctid == vv["userid"] {
				listdata[kk]["work_days"] = cast.ToString(v.SummaryInfo.WorkDays)                //应打卡天数
				listdata[kk]["regular_days"] = cast.ToString(v.SummaryInfo.RegularDays)          //正常天数
				listdata[kk]["regular_work_sec"] = cast.ToString(v.SummaryInfo.RegularWorkSec)   //实际工作时长
				listdata[kk]["standard_work_sec"] = cast.ToString(v.SummaryInfo.StandardWorkSec) //实际工作时长

				listdata[kk]["workday_over_sec"] = cast.ToString(v.OverworkInfo.WorkdayOverSec)   //工作日加班
				listdata[kk]["holidays_over_sec"] = cast.ToString(v.OverworkInfo.HolidaysOverSec) //节假日加班
				listdata[kk]["restdays_over_sec"] = cast.ToString(v.OverworkInfo.RestdaysOverSec) //休息日加班

				exceptionInfosBytes, _ := json.Marshal(v.ExceptionInfos) //异常统计
				listdata[kk]["exception_infos"] = string(exceptionInfosBytes)

				spItemsBytes, _ := json.Marshal(v.SpItems) //假勤统计
				listdata[kk]["sp_items"] = string(spItemsBytes)

				overworkInfoBytes, _ := json.Marshal(v.OverworkInfo) //假勤统计
				listdata[kk]["overwork_info"] = string(overworkInfoBytes)

				SummaryInfoBytes, _ := json.Marshal(v.SummaryInfo)
				listdata[kk]["summary_info"] = string(SummaryInfoBytes)

				fmt.Println(v.SummaryInfo.RegularWorkSec)
				fmt.Println(v.SummaryInfo.StandardWorkSec)
				fmt.Println(v.SummaryInfo.WorkDays)
				//平均工作时常
				if v.SummaryInfo.StandardWorkSec > 0 {
					rwg := cast.ToFloat64(v.SummaryInfo.RegularWorkSec) / cast.ToFloat64(3600) / cast.ToFloat64(v.SummaryInfo.WorkDays)
					listdata[kk]["regular_work_average"] = decimal.NewFromFloat(rwg).StringFixed(2)

					//listdata[kk]["jiaban"] = cast.ToString((v.SummaryInfo.RegularWorkSec - v.OverworkInfo.WorkdayOverSec - v.OverworkInfo.HolidaysOverSec - v.OverworkInfo.RestdaysOverSec))
					actual := cast.ToFloat64((v.SummaryInfo.RegularWorkSec - v.OverworkInfo.WorkdayOverSec - v.OverworkInfo.HolidaysOverSec - v.OverworkInfo.RestdaysOverSec)) / (cast.ToFloat64(v.SummaryInfo.StandardWorkSec) / cast.ToFloat64(v.SummaryInfo.WorkDays))
					listdata[kk]["regular_days"] = decimal.NewFromFloat(actual).StringFixed(2)

				} else {
					listdata[kk]["regular_work_average"] = "-"
				}

				//listdata[kk]["regular_work_average"] = ""
			}
		}
	}
	service.ReturnJson(c, 200, "操作成功", gin.H{
		"list":  listdata,
		"total": cast.ToInt(countdata[0]["total"]),
	})
}

//func (clockin Clockin) StatisticsListExport(rowCell int, page_index int, page_size int, staff string, department string, starttime int, endtime int, ExportId string) (c int, addRow int, e error) {
//	var err error
//
//	//初始化数据库
//	db := communal.Sql()
//	defer db.Close()
//
//	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(page_index)-1)*cast.ToInt(page_size), cast.ToInt(page_size))
//	//limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), 10)
//	orderstr := " order by a.`userid` desc"
//
//	wheresql := strings.Builder{}
//
//	if cast.ToString(staff) != "" {
//		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(staff)+"%"))
//	}
//	if cast.ToString(department) != "" {
//		wheresql.WriteString(fmt.Sprintf(" and FIND_IN_SET('%s', REPLACE(REPLACE(a.`department`,'[',''), ']',''))", cast.ToString(department)))
//	}
//
//	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position` from `staff` as a where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
//	listdata, err := db.QueryString(listsql)
//	if err != nil {
//		return 0, 0, err
//	}
//
//	//人员整合
//	usermap := []string{}
//	//企业微信考勤逻辑处理===========================
//	for _, v := range listdata {
//		usermap = append(usermap, v["userid"])
//	}
//
//	//========================= 开始请求数据
//	type ReqCheckinGetcheckinMonthdataStruct struct {
//		Starttime  int      `json:"starttime"`
//		Endtime    int      `json:"endtime"`
//		Useridlist []string `json:"useridlist"`
//	}
//	ReqCheckinGetcheckinMonthdata := &ReqCheckinGetcheckinMonthdataStruct{
//		Starttime:  cast.ToInt(starttime),
//		Endtime:    cast.ToInt(endtime),
//		Useridlist: usermap,
//	}
//	b, err := json.Marshal(&ReqCheckinGetcheckinMonthdata)
//	if err != nil {
//		return 0, 0, err
//	}
//	datas, err := utils.CheckinGetcheckinMonthdata(b)
//
//	destinationPath := fmt.Sprintf("./StatisticsExportTemplate_%s.xlsx", ExportId)
//	xlsx, err := excelize.OpenFile(destinationPath)
//	if err != nil {
//		return 0, 0, err
//	}
//	//=================================================== 数据写入start
//	//cell := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"}
//	row := (cast.ToInt(page_index)-1)*cast.ToInt(page_size) + 3
//
//	for _, v := range datas.Datas {
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), v.BaseInfo.Name)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), v.BaseInfo.DepartsName)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), cast.ToString(v.SummaryInfo.WorkDays))
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), cast.ToString(v.SummaryInfo.RegularDays))
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), cast.ToString(v.SummaryInfo.ExceptDays))
//
//		if len(v.ExceptionInfos) > 0 { //============================= 异常统计
//			ExceptionInfosStr := ""
//			for _, vv := range v.ExceptionInfos {
//				if vv.Exception == 1 {
//					ExceptionInfosStr += fmt.Sprintf("迟到异常/次：%d 总时间：%d \n", vv.Count, vv.Duration)
//				}
//				if vv.Exception == 2 {
//					ExceptionInfosStr += fmt.Sprintf("早退异常/次：%d 总时间：%d \n", vv.Count, vv.Duration)
//				}
//				if vv.Exception == 3 {
//					ExceptionInfosStr += fmt.Sprintf("缺卡异常/次：%d\n", vv.Count)
//				}
//				if vv.Exception == 4 {
//					ExceptionInfosStr += fmt.Sprintf("旷工异常/次：%d\n", vv.Count)
//				}
//				if vv.Exception == 5 {
//					ExceptionInfosStr += fmt.Sprintf("地点异常/次：%d\n", vv.Count)
//				}
//				if vv.Exception == 6 {
//					ExceptionInfosStr += fmt.Sprintf("设备异常/次：%d\n", vv.Count)
//				}
//			}
//			_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), ExceptionInfosStr)
//		} else {
//			_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), "")
//		}
//
//		SpItemsStr1 := ""
//		SpItemsStr2 := ""
//		SpItemsStr3 := ""
//		SpItemsStr4 := ""
//		SpItemsStr100 := ""
//		for _, vv := range v.SpItems {
//			if vv.Type == 1 {
//				SpItemsStr1 += fmt.Sprintf("%s：%d 时长：%d\n", vv.Name, vv.Count, vv.Duration)
//			}
//			if vv.Type == 2 {
//				SpItemsStr2 += fmt.Sprintf("%s：%d\n", vv.Name, vv.Count)
//			}
//			if vv.Type == 3 {
//				SpItemsStr3 += fmt.Sprintf("%s：%d\n", vv.Name, vv.Count)
//			}
//			if vv.Type == 4 {
//				SpItemsStr4 += fmt.Sprintf("%s：%d\n", vv.Name, vv.Count)
//			}
//			if vv.Type == 100 {
//				SpItemsStr100 += fmt.Sprintf("%s：%d\n", vv.Name, vv.Count)
//			}
//		}
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", row), SpItemsStr1)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("H%d", row), SpItemsStr2)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("I%d", row), SpItemsStr3)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("J%d", row), SpItemsStr4)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", row), SpItemsStr100)
//
//		OverworkInfoStr := ""
//		OverworkInfoStr += fmt.Sprintf("工作日加班时长：%d", v.OverworkInfo.WorkdayOverSec)
//		OverworkInfoStr += fmt.Sprintf("节假日加班时长：%d", v.OverworkInfo.HolidaysOverSec)
//		OverworkInfoStr += fmt.Sprintf("休息日加班时长：%d", v.OverworkInfo.RestdaysOverSec)
//		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("L%d", row), OverworkInfoStr)
//		row++
//	}
//	//=================================================== 数据写入end
//	err = xlsx.Close()
//	if err != nil {
//		return 0, err
//	}
//	err = xlsx.SaveAs(destinationPath)
//	if err != nil {
//		return 0, err
//	}
//	return len(listdata), nil
//}

func (clockin Clockin) StatisticsNotice(page_index int, page_size int, staff string, department string, starttime int, endtime int, ExportId string) (c int, e error) {
	var err error
	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(page_index)-1)*cast.ToInt(page_size), cast.ToInt(page_size))
	orderstr := " order by a.`userid` desc"

	wheresql := strings.Builder{}

	if cast.ToString(staff) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(staff)+"%"))
	}
	if cast.ToString(department) != "" {
		department, err := db.QueryString(fmt.Sprintf("select * from `department` where `id` = %s limit 1", cast.ToString(department)))
		if err != nil {
			return
		}
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", department[0]["relationship"]+"%"))
	} else {
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-1-79%"))
	}

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment`,c.`email` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		return
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(starttime),
		Endtime:    cast.ToInt(endtime),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		return
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type ReqData2Struct struct {
		Opencheckindatatype int      `json:"opencheckindatatype"`
		Starttime           int      `json:"starttime"`
		Endtime             int      `json:"endtime"`
		Useridlist          []string `json:"useridlist"`
	}
	ReqData2 := ReqData2Struct{
		Opencheckindatatype: 3,
		Starttime:           cast.ToInt(starttime),
		Endtime:             cast.ToInt(endtime) + 86400*2,
		Useridlist:          usermap,
	}
	b2, err := json.Marshal(&ReqData2)
	if err != nil {
		return
	}
	datas2, err := utils.CheckinGetcheckindata(b2)
	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海
	days := (cast.ToInt(endtime) + 86400 - cast.ToInt(starttime)) / 86400

	type PostDataStruct struct {
		To struct {
			Emails  []string `json:"emails"`
			Userids []string `json:"userids"`
		} `json:"to"`
		Subject       string `json:"subject"`
		Content       string `json:"content"`
		EnableIdTrans int    `json:"enable_id_trans"`
	}

	for _, v := range listdata {
		datemap := make(map[string]interface{})
		datemap["Days"] = days           //总天数
		datemap["TotalDays"] = 0         //排班总天数
		datemap["BusinessTripsDays"] = 0 //出差次数
		datemap["GoOutDays"] = 0         //外勤次数
		datemap["WorkOvertimeDays"] = 0  //加班天数
		datemap["OnDutyDays"] = 0        //在岗时间
		datemap["Vac1"] = 0              //年休假
		datemap["Vac2"] = 0              //调休假
		datemap["Vac3"] = 0              //事假
		datemap["Vac4"] = 0              //病假
		datemap["Vac5"] = 0              //工伤假(没有)
		datemap["Vac6"] = 0              //产假
		datemap["Vac7"] = 0              //陪产假
		datemap["Vac8"] = 0              //婚假
		datemap["Vac9"] = 0              //丧假
		datemap["Vac10"] = 0             //育儿假
		datemap["Vac11"] = 0             //补卡次数
		datemap["CheckInDays"] = 0       //打卡天数
		datemap["GoOutWelfare"] = 0      //外出补助次数
		datemap["DinnerWelfare"] = 0     //晚餐补助次数
		datemap["NightSnackWelfare"] = 0 //夜宵补助次数
		datemap["AbnormalDate"] = ""     //异常日期
		datemap["AbsenteeismDays"] = 0   //旷工天数
		datemap["IsNormal"] = 0          //是否全勤
		datemap["Overlap"] = 0           //考勤重叠
		for _, vv := range datas.Datas {
			if vv.BaseInfo.Acctid == v["userid"] {
				//时间格式化
				t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				datestr := t.Format("2006/01/02")
				fmt.Println(datestr)

				if vv.BaseInfo.RecordType == 3 {
					for kkk, vvv := range datas2.Checkindata {
						CheckinTime := time.Unix(cast.ToInt64(vvv.CheckinTime), 0).In(cstSh).Format("15:04")
						CheckinTimeSec := 0
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[0], "0")) * 3600
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[1], "0")) * 60
						if CheckinTimeSec < 14400 {
							datas2.Checkindata[kkk].SchCheckinTime = vvv.CheckinTime - CheckinTimeSec - 60
							fmt.Println("========== 转接时间", vvv.CheckinTime-CheckinTimeSec-60, vvv.CheckinTime, CheckinTimeSec)
						}
					}
				}

				WorkTime := []string{}
				for i := 0; i < len(datas2.Checkindata); i++ {
					if datas2.Checkindata[i].Userid == vv.BaseInfo.Acctid {
						SchCheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].SchCheckinTime), 0).In(cstSh)
						if datestr == SchCheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
							CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
							WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
						}
					}
				}

				//最早时间  最晚时间读取打卡记录
				if len(WorkTime) > 0 {
					startWorkTimeSec := 0
					endWorkTimeSec := 0

					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[0], "0")) * 3600
					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[1], "0")) * 60
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[0], "0")) * 3600
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[1], "0")) * 60

					if len(WorkTime) == 1 {
						vv.SummaryInfo.CheckinCount = 1
					} else if len(WorkTime) >= 2 {
						vv.SummaryInfo.CheckinCount = 2
					}

					if endWorkTimeSec < startWorkTimeSec {
						endWorkTimeSec = endWorkTimeSec + 86400
					}

					vv.SummaryInfo.RegularWorkSec = endWorkTimeSec - startWorkTimeSec
					vv.SummaryInfo.EarliestTime = startWorkTimeSec
					vv.SummaryInfo.LastestTime = endWorkTimeSec
				}

				//入职判断
				employment := v["employment"]
				if employment != "" {
					employmenttimeStamp, _ := time.ParseInLocation("2006-01-02", employment, cstSh)
					employmenttimeStampUnix := cast.ToInt64(employmenttimeStamp.Unix())
					if cast.ToInt64(vv.BaseInfo.Date) < employmenttimeStampUnix {
						continue
					}
				}

				//排班天数
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
				}

				//过年放假
				if vv.BaseInfo.RecordType == 1 && (vv.BaseInfo.Date == 1707408000 || vv.BaseInfo.Date == 1708185600) {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) - 1
					continue
				}

				//======

				for _, vvv := range vv.SpItems {
					if vvv.Duration >= 86400 {
						vvv.Duration = 28800
					}
					if vvv.Type == 1 && vvv.VacationId == 1 && vvv.Duration > 0 {
						datemap["Vac1"] = cast.ToFloat64(datemap["Vac1"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 4 && vvv.Duration > 0 {
						datemap["Vac2"] = cast.ToFloat64(datemap["Vac2"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 2 && vvv.Duration > 0 {
						datemap["Vac3"] = cast.ToFloat64(datemap["Vac3"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 3 && vvv.Duration > 0 {
						datemap["Vac4"] = cast.ToFloat64(datemap["Vac4"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 6 && vvv.Duration > 0 {
						datemap["Vac6"] = cast.ToFloat64(datemap["Vac6"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 11 && vvv.Duration > 0 {
						datemap["Vac7"] = cast.ToFloat64(datemap["Vac7"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 5 && vvv.Duration > 0 {
						datemap["Vac8"] = cast.ToFloat64(datemap["Vac8"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 9 && vvv.Duration > 0 {
						datemap["Vac9"] = cast.ToFloat64(datemap["Vac9"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 12 && vvv.Duration > 0 {
						datemap["Vac10"] = cast.ToFloat64(datemap["Vac10"]) + cast.ToFloat64(vvv.Duration)
					}
				}

				AbsenteeismNotes := ""
				RecordStatus := ""

				if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 {
					fmt.Println("============================ 打卡天数", datestr)
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
				}

				if len(vv.HolidayInfos) > 0 {
					for _, vvv := range vv.HolidayInfos {
						if strings.Contains(vvv.SpTitle.Data[0].Text, "加班") {
							datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {
							datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + 1
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
							DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							DescriptionStartSec := 0
							DescriptionEndSec := 0
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
							if DescriptionEndSec-DescriptionStartSec >= 14400 {
								datemap["GoOutWelfare"] = cast.ToInt(datemap["GoOutWelfare"]) + 1
							}
							for _, vvv := range vv.SpItems {
								if vvv.Type == 4 && vvv.Duration > 0 {
									datemap["GoOutDays"] = cast.ToInt(datemap["GoOutDays"]) + vvv.Duration
								}
							}
						}
					}
				}

				//固定上下班
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					checkin := []string{clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec), clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)}
					checkin1 := []int{0, 0}
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[0], "0")) * 3600
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[1], "0")) * 60
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[0], "0")) * 3600
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[1], "0")) * 60
					fmt.Println("============= 今日通勤", checkin1[1]-checkin1[0])

					//时间日志
					arr := [][]string{}
					arr = append(arr, []string{clockin.SecondToHours(vv.SummaryInfo.EarliestTime), clockin.SecondToHours(vv.SummaryInfo.LastestTime)}) //打卡时间

					//弹性是否关闭
					isElastic := true

					//追加请假时间节点
					if len(vv.HolidayInfos) > 0 {
						for _, vvv := range vv.HolidayInfos {
							fmt.Println(vvv)
							if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "事假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								DescriptionStartSec := 0
								DescriptionEndSec := 0
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
								if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 && DescriptionEndSec-DescriptionStartSec >= 14400 {
									datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) - 1
								}
								//重叠时间
								if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 0 && DescriptionEndSec-DescriptionStartSec > 0 {
									overlap := [][]int{}
									overlap = append(overlap, []int{vv.SummaryInfo.EarliestTime, vv.SummaryInfo.LastestTime})
									overlap = append(overlap, []int{DescriptionStartSec, DescriptionEndSec})
									sort.Slice(overlap, func(i, j int) bool {
										return overlap[i][0] < overlap[j][0]
									})
									overlapStart := math.Max(cast.ToFloat64(overlap[0][0]), cast.ToFloat64(overlap[1][0]))
									overlapEnd := math.Min(cast.ToFloat64(overlap[0][1]), cast.ToFloat64(overlap[1][1]))
									if cast.ToInt(overlapEnd) > cast.ToInt(overlapStart) {
										datemap["Overlap"] = cast.ToInt(datemap["Overlap"]) + (cast.ToInt(overlapEnd) - cast.ToInt(overlapStart))
									}
									fmt.Println("========== 重叠时间", cast.ToInt(overlapEnd), cast.ToInt(overlapStart), cast.ToInt(overlapEnd)-cast.ToInt(overlapStart))
								}
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "出差") {
								//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								//DescriptionStartSec := 0
								//DescriptionEndSec := 0
								//DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
								//DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
								//DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
								//DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
								//
								//datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + (DescriptionEndSec - DescriptionStartSec)

								//重叠时间计算
								//overlapSec := 0
								//overlap := [][]int{}
								//overlap = append(overlap, []int{vv.SummaryInfo.EarliestTime, vv.SummaryInfo.LastestTime})
								//overlap = append(overlap, []int{DescriptionStartSec, DescriptionEndSec})
								//sort.Slice(overlap, func(i, j int) bool {
								//	return overlap[i][0] < overlap[j][0]
								//})
								//overlapStart := math.Max(cast.ToFloat64(overlap[0][0]), cast.ToFloat64(overlap[1][0]))
								//overlapEnd := math.Min(cast.ToFloat64(overlap[0][1]), cast.ToFloat64(overlap[1][1]))
								//datemap["Overlap"] = cast.ToInt(datemap["Overlap"]) + (cast.ToInt(overlapEnd) - cast.ToInt(overlapStart))
								//fmt.Println("========== 重叠时间", cast.ToInt(overlapEnd), cast.ToInt(overlapStart), cast.ToInt(overlapEnd)-cast.ToInt(overlapStart))
								////for iii := 1; iii < len(overlap); iii++ {
								//	pre := overlap[iii-1]
								//	current := overlap[iii]
								//	if pre[0] <= current[1] && current[0] <= pre[1] {
								//		overlapSec += pre[1] - current[0]
								//	}
								//}
								//datemap["Overlap"] = cast.ToInt(datemap["Overlap"]) + overlapSec
							} else {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							}
							//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							//arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
						}
					}

					fmt.Println("============= 时间节点")
					fmt.Println(arr)

					//时间重写
					arr1 := [][]int{}
					for i := 0; i < len(arr); i++ {
						var q, w int
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[0], "0")) * 3600
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[1], "0")) * 60
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[0], "0")) * 3600
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[1], "0")) * 60
						arr1 = append(arr1, []int{q, w})
					}

					//进行排序
					sort.Slice(arr1, func(i, j int) bool {
						return arr1[i][0] < arr1[j][0]
					})
					//判断重叠与非重叠
					r, n := clockin.IsTimeCross(arr1)
					arr2 := []int{}
					for _, v := range arr1 {
						for _, vv := range v {
							arr2 = append(arr2, vv)
						}
					}
					sort.Ints(arr2)

					if vv.BaseInfo.RecordType == 1 { //固定班次弹性处理逻辑
						if arr2[0] > 32400 && arr2[0] <= 34200 && isElastic == true { //弹性
							i := 66600 + (arr2[0] - 32400)
							if arr2[len(arr2)-1] >= i {
								arr2[len(arr2)-1] = 66600 + (arr2[0] - 32400)
							} else {
								arr2[len(arr2)-1] = arr2[len(arr2)-1]
							}
						} else {
							arr2[len(arr2)-1] = 66600 //固定6点半
						}
					}

					if r {
						fmt.Println("今日通勤true", n, arr2[len(arr2)-1], arr2[0], arr2[len(arr2)-1]-arr2[0]) //差值
					} else {
						fmt.Println("今日通勤false", arr2[len(arr2)-1], arr2[0], n, arr2[len(arr2)-1]-arr2[0]-n) //非差值
					}

					if (vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3) && len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.CheckinCount == 2 {
							balance := 0
							if r {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0])
							} else {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0] - n)
							}
							fmt.Println("============= balance")
							fmt.Println(balance)

							if balance <= 0 {
								RecordStatus = "正常"
								AbsenteeismNotes = ""
							} else if balance > 0 && balance <= 1800 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5小时"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 1800
							} else if balance > 1800 && balance <= 3600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1小时"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 3600
							} else if balance > 3600 && balance <= 5400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1.5小时"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 5400
							} else if balance > 5400 && balance <= 7200 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工2小时"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 7200
							} else if balance > 7200 && balance <= 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 14400
							} else if balance > 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 28800
							} else if vv.SummaryInfo.EarliestTime >= 52200 { //
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 28800
							} else if vv.SummaryInfo.EarliestTime >= 39600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
								datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 14400
							}
						}

						if vv.SummaryInfo.CheckinCount <= 1 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
							datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 28800
						}
					}
				}

				for _, vvv := range vv.SpItems {
					if vvv.Type == 1 && vvv.Duration > 0 {

						if RecordStatus == "正常" {
							RecordStatus = ""
						}
						duration := 0.00
						timeType := ""
						if vvv.TimeType == 0 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
							timeType = "天"
						} else if vvv.TimeType == 1 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
							timeType = "小时"
						}
						RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration+vv.SummaryInfo.RegularWorkSec >= 28800 && vvv.VacationId == 12 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 2 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("补卡")
					}
					if vvv.Type == 3 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}

						Duration := 0
						if vvv.Duration >= 86400 {
							Duration += 28800
						} else {
							Duration = vvv.Duration
						}
						if vvv.TimeType == 0 {
							DurationSec := cast.ToFloat64(vvv.Duration) / 86400 * 28800
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + cast.ToInt(DurationSec)
						} else {
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + (Duration)
						}
					}
					if vvv.Type == 4 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 28800 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 100 && vvv.Count > 0 {
						RecordStatus += fmt.Sprintf("%s", vvv.Name)
					}
				}

				if vv.BaseInfo.RecordType == 4 {
					RecordStatus = "正常"
				}

				if vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && RecordStatus == "" {
						RecordStatus = "休息"
					}
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec && vv.SummaryInfo.RegularWorkSec >= 28800 {
							RecordStatus = "正常"
						}
					}
				}

				if vv.BaseInfo.RecordType == 5 && len(vv.BaseInfo.RuleInfo.Checkintime) == 0 && vv.SummaryInfo.CheckinCount > 0 && RecordStatus == "" {
					RecordStatus = "加班"
				}

				//外勤次数
				if vv.SummaryInfo.RegularWorkSec > 0 {
					datemap["OnDutyDays"] = cast.ToInt(datemap["OnDutyDays"]) + vv.SummaryInfo.RegularWorkSec
				}

				//免打卡班次
				if vv.BaseInfo.RecordType == 4 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
					}
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
					datemap["AbsenteeismDays"] = 0
					datemap["AbnormalDate"] = ""
					datemap["IsNormal"] = 1
					continue
				}

				//加班天数
				//if vv.BaseInfo.RecordType == 5 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.SummaryInfo.RegularWorkSec
				//}
				//if vv.OtInfo.OtStatus == 1 && vv.OtInfo.OtDuration > 0 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
				//}
				//if vv.BaseInfo.RecordType == 5 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.SummaryInfo.RegularWorkSec
				//}

				//晚餐补助(正常)
				//t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				a := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b, _ := time.ParseInLocation("2006-01-02 15:04:05", a, cstSh)
				c := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d, _ := time.ParseInLocation("2006-01-02 15:04:05", c, cstSh)
				e := b.Unix() - d.Unix()
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 && vv.SummaryInfo.EarliestTime <= 66600 {
					if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e) {
						datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
					}
				}

				////晚餐补助(直播)
				//a2 := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//b2, _ := time.ParseInLocation("2006-01-02 15:04:05", a2, cstSh)
				//c2 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//d2, _ := time.ParseInLocation("2006-01-02 15:04:05", c2, cstSh)
				//e2 := b2.Unix() - d2.Unix()
				//if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
				//	if vv.BaseInfo.RecordType == 3 && strings.Index(vv.BaseInfo.RuleInfo.Groupname, "直播") > -1 && vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec <= 66600 && vv.SummaryInfo.LastestTime >= cast.ToInt(e2) {
				//		datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
				//	}
				//}

				//宵夜补助 超过 23:00
				a1 := fmt.Sprintf("%s-%s-%s 23:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b1, _ := time.ParseInLocation("2006-01-02 15:04:05", a1, cstSh)
				c1 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d1, _ := time.ParseInLocation("2006-01-02 15:04:05", c1, cstSh)
				e1 := b1.Unix() - d1.Unix()
				if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e1) {
					datemap["NightSnackWelfare"] = cast.ToInt(datemap["NightSnackWelfare"]) + 1
				}

				if AbsenteeismNotes != "" {
					t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
					datestr := t.Format("02")
					datemap["AbnormalDate"] = cast.ToString(datemap["AbnormalDate"]) + datestr + "/"
				}
			}
		}

		AbsenteeismDaysFloat64 := cast.ToFloat64(datemap["AbsenteeismDays"]) / 3600 / 8
		//datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
		if AbsenteeismDaysFloat64 == 0 {
			datemap["AbsenteeismDays"] = 0
		} else {
			datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), "0")
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), ".")
		}

		Vac1Float64 := cast.ToFloat64(datemap["Vac1"]) / 3600 / 8
		if Vac1Float64 == 0 {
			datemap["Vac1"] = 0
		} else {
			datemap["Vac1"] = fmt.Sprintf("%.4f", Vac1Float64)
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), "0")
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), ".")
		}

		Vac2Float64 := cast.ToFloat64(datemap["Vac2"]) / 3600 / 8
		//datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
		if Vac2Float64 == 0 {
			datemap["Vac2"] = 0
		} else {
			datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), "0")
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), ".")
		}

		Vac3Float64 := cast.ToFloat64(datemap["Vac3"]) / 3600 / 8
		//datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
		if Vac3Float64 == 0 {
			datemap["Vac3"] = 0
		} else {
			datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), "0")
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), ".")
		}

		Vac4Float64 := cast.ToFloat64(datemap["Vac4"]) / 3600 / 8
		//datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
		if Vac4Float64 == 0 {
			datemap["Vac4"] = 0
		} else {
			datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), "0")
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), ".")
		}

		Vac6Float64 := cast.ToFloat64(datemap["Vac6"]) / 3600 / 8
		//datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
		if Vac6Float64 == 0 {
			datemap["Vac6"] = 0
		} else {
			datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), "0")
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), ".")
		}

		Vac7Float64 := cast.ToFloat64(datemap["Vac7"]) / 3600 / 8
		//datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
		if Vac7Float64 == 0 {
			datemap["Vac7"] = 0
		} else {
			datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), "0")
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), ".")
		}

		Vac8Float64 := cast.ToFloat64(datemap["Vac8"]) / 3600 / 8
		//datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
		if Vac8Float64 == 0 {
			datemap["Vac8"] = 0
		} else {
			datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), "0")
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), ".")
		}

		Vac9Float64 := cast.ToFloat64(datemap["Vac9"]) / 3600 / 8
		//datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
		if Vac9Float64 == 0 {
			datemap["Vac9"] = 0
		} else {
			datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), "0")
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), ".")
		}

		BusinessTripsDaysFloat64 := cast.ToFloat64(datemap["BusinessTripsDays"]) / 3600 / 8
		//datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
		if BusinessTripsDaysFloat64 == 0 {
			datemap["BusinessTripsDays"] = 0
		} else {
			datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), "0")
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), ".")
		}

		GoOutDaysFloat64 := cast.ToFloat64(datemap["GoOutDays"]) / 3600 / 8
		//datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
		if GoOutDaysFloat64 == 0 {
			datemap["GoOutDays"] = 0
		} else {
			datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), "0")
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), ".")
		}

		Vac10Float64 := cast.ToFloat64(datemap["Vac10"]) / 3600 / 8
		//datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
		if Vac10Float64 == 0 {
			datemap["Vac10"] = 0
		} else {
			datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), "0")
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), ".")
		}

		//异常天数
		AbnormalDate := cast.ToString(datemap["AbnormalDate"])
		if len(AbnormalDate) > 0 {
			AbnormalDate = strings.TrimRight(AbnormalDate, string(AbnormalDate[len(AbnormalDate)-1]))
			AbnormalDateMap := strings.Split(AbnormalDate, "/")
			sort.Strings(AbnormalDateMap)
			datemap["AbnormalDate"] = strings.Join(AbnormalDateMap, "/")
		} else {
			datemap["AbnormalDate"] = ""
		}

		WorkOvertimeDaysFloat := cast.ToFloat64(datemap["WorkOvertimeDays"]) / 3600 / 8
		//datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
		if WorkOvertimeDaysFloat == 0 {
			datemap["WorkOvertimeDays"] = 0
		} else {
			datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), "0")
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), ".")
		}

		OnDutyDaysFloat := cast.ToFloat64(datemap["OnDutyDays"]) / 3600 / 8
		datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
		if OnDutyDaysFloat == 0 {
			datemap["OnDutyDays"] = 0
		} else {
			datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), "0")
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), ".")
		}

		OverlapFloat := cast.ToFloat64(datemap["Overlap"]) / 3600 / 8
		datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
		if OverlapFloat == 0 {
			datemap["Overlap"] = 0
		} else {
			datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), "0")
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), ".")
		}

		if cast.ToString(datemap["AbnormalDate"]) == "" && cast.ToInt(datemap["Vac11"]) <= 3 {
			datemap["IsNormal"] = 1
		}
		if datas.Datas[0].BaseInfo.RecordType == 3 {
			datemap["IsNormal"] = 0
		}
		if cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac9"]) > 0 ||
			cast.ToFloat64(datemap["Vac8"]) > 0 ||
			cast.ToFloat64(datemap["Vac7"]) > 0 ||
			cast.ToFloat64(datemap["Vac6"]) > 0 ||
			cast.ToFloat64(datemap["Vac5"]) > 0 ||
			cast.ToFloat64(datemap["Vac4"]) > 0 ||
			cast.ToFloat64(datemap["Vac3"]) > 0 {
			datemap["IsNormal"] = 0
		}

		body := `<div class="container" style="margin: 0px auto; max-width: 550px; background-color: rgb(255, 255, 255); padding: 20px; border: 1px solid rgb(216, 228, 245); border-radius: 5px;">
	   <strong>{###XINGMING###}:</strong>
	   <p>工作辛苦了，您的 {###STIME-ETIME###}考勤数据统计已生成，请查看。</p>
	   <table class="table" style="width: 100%; border-spacing: 0px; border-collapse: collapse; table-layout: fixed; color: rgb(73, 78, 88); font-size: 14px;">
	       <tbody><tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">姓名</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###XINGMING###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">部门</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###BUMEN###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">总天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###ZONGTIANSHU###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">排班天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###PAIBANTIANSHU###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">打卡天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###DAKATIANSHU###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">加班(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###JIABAN###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">出差(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###CHUCHAI###}</td></tr>
	       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">外出(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###WAICHU###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">旷工时长(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###KUANGGONG###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">异常日期</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###YICHANG###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">年假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###NIANJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">调休假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###TIAOXIU###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">事假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###SHIJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">病假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###BINGJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">婚假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###HUNJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">产假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###CHANJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">陪产假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###PEICHANJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">丧假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###SANGJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">育儿假(天)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###YUEJIA###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">补卡次数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###BUKACISHU###}</td></tr>
           <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">夜宵补贴(次)</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###YEXIAOBUTIE###}</td></tr>
	   </tbody></table>
	   <p class="remark" style="color: rgb(101, 109, 125); font-size: 12px;">提示：如有考勤异常请及时处理，有任何考勤问题反馈至企业微信人事行政部梁静如。</p>
	 </div>
	`
		body = strings.Replace(body, "{###XINGMING###}", datas.Datas[0].BaseInfo.Name, -1)
		stime := time.Unix(cast.ToInt64(starttime), 0).In(cstSh)
		etime := time.Unix(cast.ToInt64(endtime), 0).In(cstSh)
		stimestr := stime.Format("2006/01/02")
		etimestr := etime.Format("2006/01/02")
		body = strings.Replace(body, "{###STIME-ETIME###}", stimestr+" 至 "+etimestr, -1)

		body = strings.Replace(body, "{###BUMEN###}", datas.Datas[0].BaseInfo.DepartsName, -1)
		body = strings.Replace(body, "{###ZONGTIANSHU###}", cast.ToString(datemap["Days"]), -1)
		body = strings.Replace(body, "{###PAIBANTIANSHU###}", cast.ToString(datemap["TotalDays"]), -1)
		body = strings.Replace(body, "{###DAKATIANSHU###}", cast.ToString(datemap["CheckInDays"]), -1)
		body = strings.Replace(body, "{###JIABAN###}", cast.ToString(datemap["WorkOvertimeDays"]), -1)
		body = strings.Replace(body, "{###CHUCHAI###}", cast.ToString(datemap["BusinessTripsDays"]), -1)
		body = strings.Replace(body, "{###WAICHU###}", cast.ToString(datemap["GoOutDays"]), -1)
		body = strings.Replace(body, "{###KUANGGONG###}", cast.ToString(datemap["AbsenteeismDays"]), -1)
		body = strings.Replace(body, "{###YICHANG###}", cast.ToString(datemap["AbnormalDate"]), -1)
		body = strings.Replace(body, "{###NIANJIA###}", cast.ToString(datemap["Vac1"]), -1)
		body = strings.Replace(body, "{###TIAOXIU###}", cast.ToString(datemap["Vac2"]), -1)
		body = strings.Replace(body, "{###SHIJIA###}", cast.ToString(datemap["Vac3"]), -1)
		body = strings.Replace(body, "{###BINGJIA###}", cast.ToString(datemap["Vac4"]), -1)
		body = strings.Replace(body, "{###HUNJIA###}", cast.ToString(datemap["Vac8"]), -1)
		body = strings.Replace(body, "{###CHANJIA###}", cast.ToString(datemap["Vac6"]), -1)
		//body = strings.Replace(body, "{###CHANJIANJIA###}", cast.ToString(datemap["Vac8"]), -1)
		body = strings.Replace(body, "{###PEICHANJIA###}", cast.ToString(datemap["Vac7"]), -1)
		body = strings.Replace(body, "{###SANGJIA###}", cast.ToString(datemap["Vac9"]), -1)
		body = strings.Replace(body, "{###YUEJIA###}", cast.ToString(datemap["Vac10"]), -1)
		body = strings.Replace(body, "{###BUKACISHU###}", cast.ToString(datemap["Vac11"]), -1)
		body = strings.Replace(body, "{###YEXIAOBUTIE###}", cast.ToString(datemap["NightSnackWelfare"]), -1)

		//datemapbyte, _ := json.Marshal(datemap)
		//listdata[k]["clockin"] = string(datemapbyte)
		fmt.Println("====== 邮件数据")
		fmt.Println(body)

		PostDataStruct := PostDataStruct{}
		PostDataStruct.To.Emails = append(PostDataStruct.To.Emails, v["email"])
		PostDataStruct.Subject = "考勤统计"
		PostDataStruct.Content = body
		b, err := json.Marshal(&PostDataStruct)
		if err != nil {
			return 0, err
		}
		emaidata, err := utils.ExmailAppCcomposeSend(b)
		//err := utils.SendEduEmail(emailStr, "考勤统计", body, "html")
		fmt.Println(emaidata)
		fmt.Println(err)
	}

	return len(listdata), nil
	//========================= enbd
	//for _, v := range datas.Datas {
	//	var emailStr string
	//	for _, vv := range listdata {
	//		if vv["userid"] == v.BaseInfo.Acctid {
	//			emailStr = vv["email"]
	//		}
	//	}
	//
	//	body := `<div class="container" style="margin: 0px auto; max-width: 550px; background-color: rgb(255, 255, 255); padding: 20px; border: 1px solid rgb(216, 228, 245); border-radius: 5px;">
	//   <strong>{###NAME###}:</strong>
	//   <p>工作辛苦了，您的 {###STIME-ETIME###}考勤数据统计已生成，请查看。</p>
	//   <table class="table" style="width: 100%; border-spacing: 0px; border-collapse: collapse; table-layout: fixed; color: rgb(73, 78, 88); font-size: 14px;">
	//       <tbody><tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">姓名</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###NAME###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">应打卡天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###work_days###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">正常天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###regular_days###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">异常天数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###except_days###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">迟到次数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###abnormal_cd###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">早退次数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###abnormal_zt###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">缺卡次数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###abnormal_qk###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">旷工次数</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###abnormal_kg###}</td></tr>
	//       {###trdata###}
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">工作日加班</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###workday_over_sec###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">节假日加班</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###holidays_over_sec###}</td></tr>
	//       <tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">休息日加班</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">{###restdays_over_sec###}</td></tr>
	//   </tbody></table>
	//   <p class="remark" style="color: rgb(101, 109, 125); font-size: 12px;">提示：如有考勤异常请及时处理，有任何考勤问题反馈至企业微信人事行政部梁静如。</p>
	// </div>
	//`
	//	body = strings.Replace(body, "{###NAME###}", v.BaseInfo.Name, -1)
	//
	//	stime := time.Unix(cast.ToInt64(starttime), 0).In(cstSh)
	//	etime := time.Unix(cast.ToInt64(endtime), 0).In(cstSh)
	//	stimestr := stime.Format("2006/01/02")
	//	etimestr := etime.Format("2006/01/02")
	//	body = strings.Replace(body, "{###STIME-ETIME###}", stimestr+" 至 "+etimestr, -1)
	//
	//	body = strings.Replace(body, "{###work_days###}", cast.ToString(v.SummaryInfo.WorkDays), -1)
	//	body = strings.Replace(body, "{###regular_days###}", cast.ToString(v.SummaryInfo.RegularDays), -1)
	//	body = strings.Replace(body, "{###except_days###}", cast.ToString(v.SummaryInfo.ExceptDays), -1)
	//
	//	body = strings.Replace(body, "{###regular_work_sec###}", cast.ToString(v.SummaryInfo.RegularWorkSec), -1)
	//	body = strings.Replace(body, "{###standard_work_sec###}", cast.ToString(v.SummaryInfo.StandardWorkSec), -1)
	//
	//	var abnormal_cd, abnormal_zt, abnormal_qk, abnormal_kg int
	//	for _, vv := range v.ExceptionInfos {
	//		if vv.Exception == 1 {
	//			abnormal_cd += vv.Count
	//		}
	//		if vv.Exception == 2 {
	//			abnormal_zt += vv.Count
	//		}
	//		if vv.Exception == 3 {
	//			abnormal_qk += vv.Count
	//		}
	//		if vv.Exception == 4 {
	//			abnormal_kg += vv.Count
	//		}
	//	}
	//	body = strings.Replace(body, "{###abnormal_cd###}", cast.ToString(abnormal_cd), -1)
	//	body = strings.Replace(body, "{###abnormal_zt###}", cast.ToString(abnormal_zt), -1)
	//	body = strings.Replace(body, "{###abnormal_qk###}", cast.ToString(abnormal_qk), -1)
	//	body = strings.Replace(body, "{###abnormal_kg###}", cast.ToString(abnormal_kg), -1)
	//
	//	var htmlstr string
	//	for _, vv := range v.SpItems {
	//		htmlstr += fmt.Sprintf(`<tr style="background-color: rgb(255, 255, 255);"><td class="field" style="text-align: right; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245); width: 180px; font-weight: bold;">%s</td><td style="text-align: left; box-sizing: border-box; overflow: hidden; padding: 5px 12px; vertical-align: middle; border: 1px solid rgb(235, 238, 245);">%d</td></tr>`, vv.Name, vv.Count)
	//	}
	//	body = strings.Replace(body, "{###trdata###}", htmlstr, -1)
	//
	//	body = strings.Replace(body, "{###workday_over_sec###}", cast.ToString(v.OverworkInfo.WorkdayOverSec), -1)
	//	body = strings.Replace(body, "{###holidays_over_sec###}", cast.ToString(v.OverworkInfo.HolidaysOverSec), -1)
	//	body = strings.Replace(body, "{###restdays_over_sec###}", cast.ToString(v.OverworkInfo.RestdaysOverSec), -1)
	//
	//	//fmt.Println(body)
	//	//ExmailAppCcomposeSend
	//
	//	PostDataStruct := PostDataStruct{}
	//	PostDataStruct.To.Emails = append(PostDataStruct.To.Emails, emailStr)
	//	PostDataStruct.Subject = "考勤统计"
	//	PostDataStruct.Content = body
	//	b, err := json.Marshal(&PostDataStruct)
	//	if err != nil {
	//		return 0, err
	//	}
	//	emaidata, err := utils.ExmailAppCcomposeSend(b)
	//	//err := utils.SendEduEmail(emailStr, "考勤统计", body, "html")
	//	fmt.Println(emaidata)
	//	fmt.Println(err)
	//}
	////=================================================== 数据写入end
	//return len(listdata), nil
}

func (clockin Clockin) DetailedStaff(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	wheresql := strings.Builder{}
	wheresql.WriteString(fmt.Sprintf(" and a.`userid` = '%s'", cast.ToString(jsondata["userid"])))

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s limit 1", wheresql.String())
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(jsondata["starttime"]),
		Endtime:    cast.ToInt(jsondata["endtime"]),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type ReqData2Struct struct {
		Opencheckindatatype int      `json:"opencheckindatatype"`
		Starttime           int      `json:"starttime"`
		Endtime             int      `json:"endtime"`
		Useridlist          []string `json:"useridlist"`
	}
	ReqData2 := ReqData2Struct{
		Opencheckindatatype: 3,
		Starttime:           cast.ToInt(jsondata["starttime"]),
		Endtime:             cast.ToInt(jsondata["endtime"]) + 86400*2,
		Useridlist:          usermap,
	}
	b2, err := json.Marshal(&ReqData2)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas2, err := utils.CheckinGetcheckindata(b2)

	fmt.Println("====== 打开记录打印")
	testdata2, _ := json.Marshal(datas2)
	fmt.Println(string(testdata2))

	type CheckintimeStruct struct {
		WorkSec    string `json:"work_sec"`
		OffWorkSec string `json:"off_work_sec"`
	}
	type datemapStruct struct {
		Date             string              `json:"date"`
		Weekday          string              `json:"weekday"`
		AbsenteeismNotes string              `json:"absenteeism_notes"`
		Checkintime      []CheckintimeStruct `json:"checkintime"`
		SummaryInfo      struct {
			CheckinCount int    `json:"checkin_count"`
			EarliestTime string `json:"earliest_time"`
			LastestTime  string `json:"lastest_time"`
		} `json:"summary_info"`
		RecordType     int    `json:"record_type"`
		RecordStatus   string `json:"record_status"`
		Groupname      string `json:"groupname"`
		ExceptionInfos []struct {
			Count     int `json:"count"`
			Duration  int `json:"duration"`
			Exception int `json:"exception"`
		} `json:"exception_infos"`
		WorkTime []string `json:"worktime"`
	}
	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海

	for k, v := range listdata {
		datemap := []datemapStruct{}

		for _, vv := range datas.Datas {
			if vv.BaseInfo.Acctid == v["userid"] {
				//过年放假
				if vv.BaseInfo.RecordType == 1 && (vv.BaseInfo.Date == 1707408000 || vv.BaseInfo.Date == 1708185600) {
					continue
				}

				//入职判断
				employment := v["employment"]
				if employment != "" {
					employmenttimeStamp, _ := time.ParseInLocation("2006-01-02", employment, cstSh)
					employmenttimeStampUnix := cast.ToInt64(employmenttimeStamp.Unix())
					if cast.ToInt64(vv.BaseInfo.Date) < employmenttimeStampUnix {
						continue
					}
				}

				//时间格式化
				t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				datestr := t.Format("2006/01/02")

				if vv.BaseInfo.RecordType == 3 {
					for kkk, vvv := range datas2.Checkindata {
						CheckinTime := time.Unix(cast.ToInt64(vvv.CheckinTime), 0).In(cstSh).Format("15:04")
						CheckinTimeSec := 0
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[0], "0")) * 3600
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[1], "0")) * 60
						if CheckinTimeSec < 14400 {
							datas2.Checkindata[kkk].SchCheckinTime = vvv.CheckinTime - CheckinTimeSec - 60
							fmt.Println("========== 转接时间", vvv.CheckinTime-CheckinTimeSec-60, vvv.CheckinTime, CheckinTimeSec)
						}
					}
				}

				WorkTime := []string{}
				for i := 0; i < len(datas2.Checkindata); i++ {
					if datas2.Checkindata[i].Userid == vv.BaseInfo.Acctid {
						if datas2.Checkindata[i].SchCheckinTime > 0 {
							SchCheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].SchCheckinTime), 0).In(cstSh)
							if datestr == SchCheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						} else {
							CheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
							if datestr == CheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						}
					}
				}

				//最早时间  最晚时间读取打卡记录
				if len(WorkTime) > 0 {
					startWorkTimeSec := 0
					endWorkTimeSec := 0

					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[0], "0")) * 3600
					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[1], "0")) * 60
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[0], "0")) * 3600
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[1], "0")) * 60

					if len(WorkTime) == 1 {
						vv.SummaryInfo.CheckinCount = 1
					} else if len(WorkTime) >= 2 {
						vv.SummaryInfo.CheckinCount = 2
					}

					if endWorkTimeSec < startWorkTimeSec {
						endWorkTimeSec = endWorkTimeSec + 86400
					}

					vv.SummaryInfo.RegularWorkSec = endWorkTimeSec - startWorkTimeSec
					vv.SummaryInfo.EarliestTime = startWorkTimeSec
					vv.SummaryInfo.LastestTime = endWorkTimeSec
				}

				//早退或者异常查看是否正确
				for kkk, vvv := range vv.ExceptionInfos {
					if (vvv.Exception == 1 || vvv.Exception == 2) && vv.SummaryInfo.CheckinCount == 2 && vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec {
						vv.ExceptionInfos = append(vv.ExceptionInfos[:kkk], vv.ExceptionInfos[kkk+1:]...)
					}
				}

				//打卡处理
				SummaryInfo := datemapStruct{}.SummaryInfo
				SummaryInfo.CheckinCount = vv.SummaryInfo.CheckinCount
				SummaryInfo.EarliestTime = clockin.SecondToHours(vv.SummaryInfo.EarliestTime)
				SummaryInfo.LastestTime = clockin.SecondToHours(vv.SummaryInfo.LastestTime)

				Checkintime := datemapStruct{}.Checkintime
				for _, vvvv := range vv.BaseInfo.RuleInfo.Checkintime {
					Checkintime = append(Checkintime, CheckintimeStruct{
						WorkSec:    clockin.SecondToHours(vvvv.WorkSec),
						OffWorkSec: clockin.SecondToHours(vvvv.OffWorkSec),
					})
				}

				if len(WorkTime) <= 0 && len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && vv.SummaryInfo.CheckinCount > 0 {
					WorkTime = append(WorkTime, clockin.SecondToHours(vv.SummaryInfo.EarliestTime))
					WorkTime = append(WorkTime, clockin.SecondToHours(vv.SummaryInfo.LastestTime))
				}

				RecordStatus := ""
				AbsenteeismNotes := ""

				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					checkin := []string{clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec), clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)}
					checkin1 := []int{0, 0}
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[0], "0")) * 3600
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[1], "0")) * 60
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[0], "0")) * 3600
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[1], "0")) * 60
					fmt.Println("============= 今日通勤", checkin1[1]-checkin1[0])

					//时间日志
					arr := [][]string{}
					arr = append(arr, []string{clockin.SecondToHours(vv.SummaryInfo.EarliestTime), clockin.SecondToHours(vv.SummaryInfo.LastestTime)}) //打卡时间

					//弹性是否关闭
					isElastic := true

					//追加请假时间节点
					if len(vv.HolidayInfos) > 0 {
						for _, vvv := range vv.HolidayInfos {
							fmt.Println(vvv)
							if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "加班") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "年假") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "事假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								//fmt.Println("====== 值", DescriptionStart)
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							} else {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								//fmt.Println("====== 值", DescriptionStart)
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							}
							//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							//arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
						}
					}

					fmt.Println("============= 时间节点")
					fmt.Println(arr)

					//时间重写
					arr1 := [][]int{}
					for i := 0; i < len(arr); i++ {
						var q, w int
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[0], "0")) * 3600
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[1], "0")) * 60
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[0], "0")) * 3600
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[1], "0")) * 60
						arr1 = append(arr1, []int{q, w})
					}

					//进行排序
					sort.Slice(arr1, func(i, j int) bool {
						return arr1[i][0] < arr1[j][0]
					})
					//判断重叠与非重叠
					r, n := clockin.IsTimeCross(arr1)
					arr2 := []int{}
					for _, v := range arr1 {
						for _, vv := range v {
							arr2 = append(arr2, vv)
						}
					}
					sort.Ints(arr2)

					if vv.BaseInfo.RecordType == 1 { //固定班次弹性处理逻辑
						if arr2[0] > 32400 && arr2[0] <= 34200 && isElastic == true { //弹性
							i := 66600 + (arr2[0] - 32400)
							if arr2[len(arr2)-1] >= i {
								arr2[len(arr2)-1] = 66600 + (arr2[0] - 32400)
							} else {
								arr2[len(arr2)-1] = arr2[len(arr2)-1]
							}
						} else {
							arr2[len(arr2)-1] = 66600 //固定6点半
						}
					}

					if r {
						fmt.Println("今日通勤true", arr2[len(arr2)-1], arr2[0], arr2[len(arr2)-1]-arr2[0]) //差值
					} else {
						fmt.Println("今日通勤false", arr2[len(arr2)-1], arr2[0], n, arr2[len(arr2)-1]-arr2[0]-n) //非差值
					}

					if (vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3) && len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.CheckinCount == 2 {
							balance := 0
							if r {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0])
							} else {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0] - n)
							}
							fmt.Println("============= balance")
							fmt.Println(balance)

							if balance <= 0 {
								RecordStatus = "正常"
								AbsenteeismNotes = ""
							} else if balance > 0 && balance <= 1800 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5小时"
							} else if balance > 1800 && balance <= 3600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1小时"
							} else if balance > 3600 && balance <= 5400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1.5小时"
							} else if balance > 5400 && balance < 7200 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工2小时"
							} else if balance > 7200 && balance <= 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							} else if balance > 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 52200 { //
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 39600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							}
						}
						if vv.SummaryInfo.CheckinCount <= 1 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					}
				}

				if vv.BaseInfo.RecordType == 4 {
					RecordStatus = "正常"
				}

				if vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && RecordStatus == "" {
						RecordStatus = "休息"
					}
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec && vv.SummaryInfo.RegularWorkSec >= 28800 {
							RecordStatus = "正常"
						}
					}
				}

				if vv.BaseInfo.RecordType == 5 && len(vv.BaseInfo.RuleInfo.Checkintime) == 0 && vv.SummaryInfo.CheckinCount > 0 && RecordStatus == "" {
					RecordStatus = "加班"
				}

				for _, vvv := range vv.SpItems {
					if vvv.Type == 1 && vvv.Duration > 0 {
						//AbsenteeismNotes = ""
						fmt.Println("======================= 请假统计")
						fmt.Println("日期：", datestr)
						fmt.Println("vvv:", vvv)

						if RecordStatus == "正常" {
							RecordStatus = ""
						}
						duration := 0.00
						timeType := ""
						if vvv.TimeType == 0 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
							timeType = "天"
						} else if vvv.TimeType == 1 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
							timeType = "小时"
						}
						RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 && vvv.TimeType == 0 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 28800 && vvv.TimeType == 1 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration+vv.SummaryInfo.RegularWorkSec >= 28800 && vvv.VacationId == 12 {
							AbsenteeismNotes = ""
						}

					}
					if vvv.Type == 2 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("补卡")
					}
					if vvv.Type == 3 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 4 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}
						if vvv.Duration == 28800 {
							AbsenteeismNotes = ""
							RecordStatus = "正常"
						}
					}
					if vvv.Type == 100 && vvv.Count > 0 {
						RecordStatus += fmt.Sprintf("%s", vvv.Name)
					}
				}

				if len(vv.HolidayInfos) > 0 {
					RecordStatus = ""
					for _, vvv := range vv.HolidayInfos {
						RecordStatus += fmt.Sprintf("%s(%s) \r\n", vvv.SpTitle.Data[0].Text, vvv.SpDescription.Data[0].Text)
					}
				}

				datemap = append(datemap, datemapStruct{
					Date:             datestr,
					Weekday:          weekDayString(vv.BaseInfo.Date),
					Checkintime:      Checkintime,
					SummaryInfo:      SummaryInfo,
					RecordType:       vv.BaseInfo.RecordType,
					RecordStatus:     RecordStatus,
					Groupname:        vv.BaseInfo.RuleInfo.Groupname,
					ExceptionInfos:   nil,
					AbsenteeismNotes: AbsenteeismNotes,
					WorkTime:         WorkTime,
				})
			}
		}
		datemapbyte, _ := json.Marshal(datemap)
		listdata[k]["clockin"] = string(datemapbyte)
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{
		"info": listdata[0],
	})
}

func (clockin Clockin) StatisticsListNew(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), cast.ToInt(jsondata["page_size"]))
	orderstr := " order by a.`userid` desc"

	wheresql := strings.Builder{}

	if cast.ToString(jsondata["staff"]) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(jsondata["staff"])+"%"))
	}
	if cast.ToString(jsondata["department"]) != "" {
		department, err := db.QueryString(fmt.Sprintf("select * from `department` where `id` = %s limit 1", cast.ToString(jsondata["department"])))
		if err != nil {
			service.ReturnJson(c, 500, err.Error(), gin.H{})
			return
		}
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", department[0]["relationship"]+"%"))
	} else {
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-1-79%"))
	}

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	countsql := fmt.Sprintf("select count(*) as total from `staff` as a left join department b on a.main_department = b.id where 1=1 %s", wheresql.String())
	countdata, err := db.QueryString(countsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(jsondata["starttime"]),
		Endtime:    cast.ToInt(jsondata["endtime"]),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type ReqData2Struct struct {
		Opencheckindatatype int      `json:"opencheckindatatype"`
		Starttime           int      `json:"starttime"`
		Endtime             int      `json:"endtime"`
		Useridlist          []string `json:"useridlist"`
	}
	ReqData2 := ReqData2Struct{
		Opencheckindatatype: 3,
		Starttime:           cast.ToInt(jsondata["starttime"]),
		Endtime:             cast.ToInt(jsondata["endtime"]) + 86400*2,
		Useridlist:          usermap,
	}
	b2, err := json.Marshal(&ReqData2)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas2, err := utils.CheckinGetcheckindata(b2)

	////审批单统计补卡
	//type FiltersStruct struct {
	//	Key   string `json:"key"`
	//	Value string `json:"value"`
	//}
	//type ReqData3Struct struct {
	//	Starttime int             `json:"starttime"`
	//	Endtime   int             `json:"endtime"`
	//	NewCursor string          `json:"new_cursor"`
	//	Size      int             `json:"size"`
	//	Filters   []FiltersStruct `json:"filters"`
	//}

	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海
	days := (cast.ToInt(jsondata["endtime"]) + 86400 - cast.ToInt(jsondata["starttime"])) / 86400

	for k, v := range listdata {
		datemap := make(map[string]interface{})
		datemap["Days"] = days           //总天数
		datemap["TotalDays"] = 0         //排班总天数
		datemap["BusinessTripsDays"] = 0 //出差次数
		datemap["GoOutDays"] = 0         //外勤次数
		datemap["WorkOvertimeDays"] = 0  //加班天数
		datemap["OnDutyDays"] = 0        //在岗时间
		datemap["Vac1"] = 0              //年休假
		datemap["Vac2"] = 0              //调休假
		datemap["Vac3"] = 0              //事假
		datemap["Vac4"] = 0              //病假
		datemap["Vac5"] = 0              //工伤假(没有)
		datemap["Vac6"] = 0              //产假
		datemap["Vac7"] = 0              //陪产假
		datemap["Vac8"] = 0              //婚假
		datemap["Vac9"] = 0              //丧假
		datemap["Vac10"] = 0             //育儿假
		datemap["Vac11"] = 0             //补卡次数
		datemap["CheckInDays"] = 0       //打卡天数
		datemap["GoOutWelfare"] = 0      //外出补助次数
		datemap["DinnerWelfare"] = 0     //晚餐补助次数
		datemap["NightSnackWelfare"] = 0 //夜宵补助次数
		datemap["AbnormalDate"] = ""     //异常日期
		datemap["AbsenteeismDays"] = 0   //旷工天数
		datemap["IsNormal"] = 0          //是否全勤
		datemap["Overlap"] = 0           //考勤重叠

		RecordType := 0
		for i := 0; i < len(datas.Datas); i++ {
			if datas.Datas[i].BaseInfo.Acctid == v["userid"] {
				RecordType = datas.Datas[i].BaseInfo.RecordType
			}
		}

		for _, vv := range datas.Datas {
			if vv.BaseInfo.Acctid == v["userid"] {
				//时间格式化
				t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				datestr := t.Format("2006/01/02")
				fmt.Println(datestr)

				//在岗时间
				if vv.SummaryInfo.RegularWorkSec > 0 {
					datemap["OnDutyDays"] = cast.ToInt(datemap["OnDutyDays"]) + vv.SummaryInfo.RegularWorkSec
				}

				if vv.BaseInfo.RecordType == 3 {
					for kkk, vvv := range datas2.Checkindata {
						CheckinTime := time.Unix(cast.ToInt64(vvv.CheckinTime), 0).In(cstSh).Format("15:04")
						CheckinTimeSec := 0
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[0], "0")) * 3600
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[1], "0")) * 60
						if CheckinTimeSec < 14400 {
							datas2.Checkindata[kkk].SchCheckinTime = vvv.CheckinTime - CheckinTimeSec - 60
							fmt.Println("========== 转接时间", vvv.CheckinTime-CheckinTimeSec-60, vvv.CheckinTime, CheckinTimeSec)
						}
					}
				}

				//isAddKey := 0
				WorkTime := []string{}
				for i := 0; i < len(datas2.Checkindata); i++ {
					if datas2.Checkindata[i].Userid == vv.BaseInfo.Acctid {
						if datas2.Checkindata[i].SchCheckinTime > 0 {
							SchCheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].SchCheckinTime), 0).In(cstSh)
							if datestr == SchCheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						} else {
							CheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
							if datestr == CheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								//isAddKey = i
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						}
					}
				}

				//最早时间  最晚时间读取打卡记录
				if len(WorkTime) > 0 {
					startWorkTimeSec := 0
					endWorkTimeSec := 0

					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[0], "0")) * 3600
					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[1], "0")) * 60
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[0], "0")) * 3600
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[1], "0")) * 60

					if len(WorkTime) == 1 {
						vv.SummaryInfo.CheckinCount = 1
					} else if len(WorkTime) >= 2 {
						vv.SummaryInfo.CheckinCount = 2
					}

					if endWorkTimeSec < startWorkTimeSec {
						endWorkTimeSec = endWorkTimeSec + 86400
					}

					vv.SummaryInfo.RegularWorkSec = endWorkTimeSec - startWorkTimeSec
					vv.SummaryInfo.EarliestTime = startWorkTimeSec
					vv.SummaryInfo.LastestTime = endWorkTimeSec
				}

				//if datas2.Checkindata[isAddKey].Deviceid == "" && datas2.Checkindata[isAddKey].Wifiname == "" {
				//	isAdd := 1
				//	if len(vv.HolidayInfos) > 0 {
				//		for _, vvv := range vv.HolidayInfos {
				//			for _, vvvv := range vvv.SpTitle.Data {
				//				if strings.Contains(vvvv.Text, "补卡") {
				//					isAdd = 0
				//				}
				//			}
				//		}
				//	}
				//	if isAdd == 1 {
				//		datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + 1
				//	}
				//}

				//入职判断
				employment := v["employment"]
				if employment != "" {
					employmenttimeStamp, _ := time.ParseInLocation("2006-01-02", employment, cstSh)
					employmenttimeStampUnix := cast.ToInt64(employmenttimeStamp.Unix())
					if cast.ToInt64(vv.BaseInfo.Date) < employmenttimeStampUnix {
						continue
					}
				}

				//排班天数
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
				}

				//过年放假
				if vv.BaseInfo.RecordType == 1 && (vv.BaseInfo.Date == 1707408000 || vv.BaseInfo.Date == 1708185600) {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) - 1
					continue
				}

				//======

				for _, vvv := range vv.SpItems {
					if vvv.Duration >= 86400 {
						vvv.Duration = 28800
					}
					if vvv.Type == 1 && vvv.VacationId == 1 && vvv.Duration > 0 {
						datemap["Vac1"] = cast.ToFloat64(datemap["Vac1"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 4 && vvv.Duration > 0 {
						var duration float64
						if vvv.TimeType == 0 { //天
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400) * cast.ToFloat64(28800)
						} else if vvv.TimeType == 1 { //小时

						}
						datemap["Vac2"] = cast.ToFloat64(datemap["Vac2"]) + duration
					}
					if vvv.Type == 1 && vvv.VacationId == 2 && vvv.Duration > 0 {
						datemap["Vac3"] = cast.ToFloat64(datemap["Vac3"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 3 && vvv.Duration > 0 {
						var duration float64
						if vvv.TimeType == 0 { //天
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400) * cast.ToFloat64(28800)
						} else if vvv.TimeType == 1 { //小时

						}
						datemap["Vac4"] = cast.ToFloat64(datemap["Vac4"]) + duration
					}
					if vvv.Type == 1 && vvv.VacationId == 6 && vvv.Duration > 0 {
						datemap["Vac6"] = cast.ToFloat64(datemap["Vac6"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 11 && vvv.Duration > 0 {
						datemap["Vac7"] = cast.ToFloat64(datemap["Vac7"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 5 && vvv.Duration > 0 {
						datemap["Vac8"] = cast.ToFloat64(datemap["Vac8"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 9 && vvv.Duration > 0 {
						datemap["Vac9"] = cast.ToFloat64(datemap["Vac9"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 12 && vvv.Duration > 0 {
						datemap["Vac10"] = cast.ToFloat64(datemap["Vac10"]) + cast.ToFloat64(vvv.Duration)
					}
				}

				AbsenteeismNotes := ""
				RecordStatus := ""

				if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 {
					fmt.Println("============================ 打卡天数", datestr)
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
				}

				if len(vv.HolidayInfos) > 0 {
					for _, vvv := range vv.HolidayInfos {
						if strings.Contains(vvv.SpTitle.Data[0].Text, "加班") {
							datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {
							datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + 1
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
							DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							DescriptionStartSec := 0
							DescriptionEndSec := 0
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
							if DescriptionEndSec-DescriptionStartSec >= 14400 {
								datemap["GoOutWelfare"] = cast.ToInt(datemap["GoOutWelfare"]) + 1
							}
							if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 && DescriptionEndSec-DescriptionStartSec >= 14400 {
								datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) - 1
							}
							for _, vvv := range vv.SpItems {
								if vvv.Type == 4 && vvv.Duration > 0 {
									datemap["GoOutDays"] = cast.ToInt(datemap["GoOutDays"]) + vvv.Duration
								}
							}
						}
					}
				}

				//固定上下班
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					checkin := []string{clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec), clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)}
					checkin1 := []int{0, 0}
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[0], "0")) * 3600
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[1], "0")) * 60
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[0], "0")) * 3600
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[1], "0")) * 60
					fmt.Println("============= 今日通勤", checkin1[1]-checkin1[0])

					//时间日志
					arr := [][]string{}
					arr = append(arr, []string{clockin.SecondToHours(vv.SummaryInfo.EarliestTime), clockin.SecondToHours(vv.SummaryInfo.LastestTime)}) //打卡时间

					//弹性是否关闭
					isElastic := true

					//追加请假时间节点
					if len(vv.HolidayInfos) > 0 {
						for _, vvv := range vv.HolidayInfos {
							fmt.Println(vvv)
							if strings.Contains(vvv.SpTitle.Data[0].Text, "年假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "事假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								fmt.Println("============================= 外出外出")

								if DescriptionStart == "14:00" {
									fmt.Println("============================= 外出外出补充时间")
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}

								DescriptionStartSec := 0
								DescriptionEndSec := 0
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
								//if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 && DescriptionEndSec-DescriptionStartSec >= 14400 {
								//	datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) - 1
								//}

								//重叠时间
								if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 0 && DescriptionEndSec-DescriptionStartSec > 0 {
									overlap := [][]int{}
									overlap = append(overlap, []int{vv.SummaryInfo.EarliestTime, vv.SummaryInfo.LastestTime})
									overlap = append(overlap, []int{DescriptionStartSec, DescriptionEndSec})
									sort.Slice(overlap, func(i, j int) bool {
										return overlap[i][0] < overlap[j][0]
									})
									overlapStart := math.Max(cast.ToFloat64(overlap[0][0]), cast.ToFloat64(overlap[1][0]))
									overlapEnd := math.Min(cast.ToFloat64(overlap[0][1]), cast.ToFloat64(overlap[1][1]))
									if cast.ToInt(overlapEnd) > cast.ToInt(overlapStart) {
										datemap["Overlap"] = cast.ToInt(datemap["Overlap"]) + (cast.ToInt(overlapEnd) - cast.ToInt(overlapStart))
									}
									fmt.Println("========== 重叠时间", cast.ToInt(overlapEnd), cast.ToInt(overlapStart), cast.ToInt(overlapEnd)-cast.ToInt(overlapStart))
								}
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {

							} else {
								fmt.Println("======================= 报错报错", vvv.SpDescription.Data[0].Text)
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							}
							//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							//arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
						}
					}

					fmt.Println("============= 时间节点")
					fmt.Println(arr)

					//时间重写
					arr1 := [][]int{}
					for i := 0; i < len(arr); i++ {
						var q, w int
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[0], "0")) * 3600
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[1], "0")) * 60
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[0], "0")) * 3600
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[1], "0")) * 60
						arr1 = append(arr1, []int{q, w})
					}

					//进行排序
					sort.Slice(arr1, func(i, j int) bool {
						return arr1[i][0] < arr1[j][0]
					})
					//判断重叠与非重叠
					r, n := clockin.IsTimeCross(arr1)
					arr2 := []int{}
					for _, v := range arr1 {
						for _, vv := range v {
							arr2 = append(arr2, vv)
						}
					}
					sort.Ints(arr2)

					if vv.BaseInfo.RecordType == 1 { //固定班次弹性处理逻辑
						if arr2[0] > 32400 && arr2[0] <= 34200 && isElastic == true { //弹性
							i := 66600 + (arr2[0] - 32400)
							if arr2[len(arr2)-1] >= i {
								arr2[len(arr2)-1] = 66600 + (arr2[0] - 32400)
							} else {
								arr2[len(arr2)-1] = arr2[len(arr2)-1]
							}
						} else {
							arr2[len(arr2)-1] = 66600 //固定6点半
						}
					}

					if r {
						fmt.Println("今日通勤true", n, arr2[len(arr2)-1], arr2[0], arr2[len(arr2)-1]-arr2[0]) //差值
					} else {
						fmt.Println("今日通勤false", arr2[len(arr2)-1], arr2[0], n, arr2[len(arr2)-1]-arr2[0]-n) //非差值
					}

					if (vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3) && len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.CheckinCount == 2 {
							balance := 0
							if r {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0])
							} else {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0] - n)
							}
							fmt.Println("============= balance")
							fmt.Println(balance)

							if balance <= 0 {
								RecordStatus = "正常"
								AbsenteeismNotes = ""
							} else if balance > 0 && balance <= 1800 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5小时"
							} else if balance > 1800 && balance <= 3600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1小时"
							} else if balance > 3600 && balance <= 5400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1.5小时"
							} else if balance > 5400 && balance <= 7200 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工2小时"
							} else if balance > 7200 && balance <= 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							} else if balance > 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 52200 { //
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 39600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							}
						}

						if vv.SummaryInfo.CheckinCount <= 1 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					}
				}

				for _, vvv := range vv.SpItems {
					if vvv.Type == 1 && vvv.Duration > 0 {

						if RecordStatus == "正常" {
							RecordStatus = ""
						}
						duration := 0.00
						timeType := ""
						if vvv.TimeType == 0 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
							timeType = "天"
						} else if vvv.TimeType == 1 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
							timeType = "小时"
						}
						RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 && vvv.TimeType == 0 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 28800 && vvv.TimeType == 1 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration+vv.SummaryInfo.RegularWorkSec >= 28800 && vvv.VacationId == 12 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 2 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("补卡")
					}
					if vvv.Type == 3 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}

						Duration := 0
						if vvv.Duration >= 86400 {
							Duration += 28800
						} else {
							Duration = vvv.Duration
						}
						if vvv.TimeType == 0 {
							DurationSec := cast.ToFloat64(vvv.Duration) / 86400 * 28800
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + cast.ToInt(DurationSec)
						} else {
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + (Duration)
						}
					}
					if vvv.Type == 4 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 28800 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 100 && vvv.Count > 0 {
						RecordStatus += fmt.Sprintf("%s", vvv.Name)
					}
				}

				if vv.BaseInfo.RecordType == 4 {
					RecordStatus = "正常"
				}

				if vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && RecordStatus == "" {
						RecordStatus = "休息"
					}
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec && vv.SummaryInfo.RegularWorkSec >= 28800 {
							RecordStatus = "正常"
						}
					}
				}

				if vv.BaseInfo.RecordType == 5 && len(vv.BaseInfo.RuleInfo.Checkintime) == 0 && vv.SummaryInfo.CheckinCount > 0 && RecordStatus == "" {
					RecordStatus = "加班"
				}

				//免打卡班次
				if vv.BaseInfo.RecordType == 4 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
					}
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
					datemap["AbsenteeismDays"] = 0
					datemap["AbnormalDate"] = ""
					datemap["IsNormal"] = 1
					continue
				}

				//加班天数
				//if vv.BaseInfo.RecordType == 5 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.SummaryInfo.RegularWorkSec
				//}
				//if vv.OtInfo.OtStatus == 1 && vv.OtInfo.OtDuration > 0 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
				//}
				//if vv.BaseInfo.RecordType == 5 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.SummaryInfo.RegularWorkSec
				//}

				//晚餐补助(正常)
				//t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				a := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b, _ := time.ParseInLocation("2006-01-02 15:04:05", a, cstSh)
				c := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d, _ := time.ParseInLocation("2006-01-02 15:04:05", c, cstSh)
				e := b.Unix() - d.Unix()
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 && vv.SummaryInfo.EarliestTime <= 66600 {
					if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e) {
						datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
					}
				}

				////晚餐补助(直播)
				//a2 := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//b2, _ := time.ParseInLocation("2006-01-02 15:04:05", a2, cstSh)
				//c2 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//d2, _ := time.ParseInLocation("2006-01-02 15:04:05", c2, cstSh)
				//e2 := b2.Unix() - d2.Unix()
				//if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
				//	if vv.BaseInfo.RecordType == 3 && strings.Index(vv.BaseInfo.RuleInfo.Groupname, "直播") > -1 && vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec <= 66600 && vv.SummaryInfo.LastestTime >= cast.ToInt(e2) {
				//		datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
				//	}
				//}

				//宵夜补助 超过 23:00
				a1 := fmt.Sprintf("%s-%s-%s 23:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b1, _ := time.ParseInLocation("2006-01-02 15:04:05", a1, cstSh)
				c1 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d1, _ := time.ParseInLocation("2006-01-02 15:04:05", c1, cstSh)
				e1 := b1.Unix() - d1.Unix()
				if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e1) {
					datemap["NightSnackWelfare"] = cast.ToInt(datemap["NightSnackWelfare"]) + 1
				}

				if AbsenteeismNotes != "" {
					t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
					datestr := t.Format("02")
					datemap["AbnormalDate"] = cast.ToString(datemap["AbnormalDate"]) + datestr + "/"
				}

				if AbsenteeismNotes == "旷工0.5小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 1800
				} else if AbsenteeismNotes == "旷工1小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 3600
				} else if AbsenteeismNotes == "旷工1.5小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 5400
				} else if AbsenteeismNotes == "旷工2小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 7200
				} else if AbsenteeismNotes == "旷工0.5天" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 14400
				} else if AbsenteeismNotes == "旷工1天" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 28800
				}
			}
		}

		OnDutyDaysFloat := cast.ToFloat64(datemap["OnDutyDays"]) + cast.ToFloat64(datemap["BusinessTripsDays"]) + cast.ToFloat64(datemap["GoOutDays"])
		OnDutyDaysFloat = OnDutyDaysFloat / 3600 / 8
		datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
		if OnDutyDaysFloat == 0 {
			datemap["OnDutyDays"] = 0
		} else {
			datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), "0")
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), ".")
		}

		AbsenteeismDaysFloat64 := cast.ToFloat64(datemap["AbsenteeismDays"]) / 3600 / 8
		//datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
		if AbsenteeismDaysFloat64 == 0 {
			datemap["AbsenteeismDays"] = 0
		} else {
			datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), "0")
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), ".")
		}

		Vac1Float64 := cast.ToFloat64(datemap["Vac1"]) / 3600 / 8
		if Vac1Float64 == 0 {
			datemap["Vac1"] = 0
		} else {
			datemap["Vac1"] = fmt.Sprintf("%.4f", Vac1Float64)
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), "0")
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), ".")
		}

		Vac2Float64 := cast.ToFloat64(datemap["Vac2"]) / 3600 / 8
		//datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
		if Vac2Float64 == 0 {
			datemap["Vac2"] = 0
		} else {
			datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), "0")
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), ".")
		}

		Vac3Float64 := cast.ToFloat64(datemap["Vac3"]) / 3600 / 8
		//datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
		if Vac3Float64 == 0 {
			datemap["Vac3"] = 0
		} else {
			datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), "0")
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), ".")
		}

		Vac4Float64 := cast.ToFloat64(datemap["Vac4"]) / 3600 / 8
		//datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
		if Vac4Float64 == 0 {
			datemap["Vac4"] = 0
		} else {
			datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), "0")
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), ".")
		}

		Vac6Float64 := cast.ToFloat64(datemap["Vac6"]) / 3600 / 8
		//datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
		if Vac6Float64 == 0 {
			datemap["Vac6"] = 0
		} else {
			datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), "0")
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), ".")
		}

		Vac7Float64 := cast.ToFloat64(datemap["Vac7"]) / 3600 / 8
		//datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
		if Vac7Float64 == 0 {
			datemap["Vac7"] = 0
		} else {
			datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), "0")
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), ".")
		}

		Vac8Float64 := cast.ToFloat64(datemap["Vac8"]) / 3600 / 8
		//datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
		if Vac8Float64 == 0 {
			datemap["Vac8"] = 0
		} else {
			datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), "0")
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), ".")
		}

		Vac9Float64 := cast.ToFloat64(datemap["Vac9"]) / 3600 / 8
		//datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
		if Vac9Float64 == 0 {
			datemap["Vac9"] = 0
		} else {
			datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), "0")
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), ".")
		}

		BusinessTripsDaysFloat64 := cast.ToFloat64(datemap["BusinessTripsDays"]) / 3600 / 8
		//datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
		if BusinessTripsDaysFloat64 == 0 {
			datemap["BusinessTripsDays"] = 0
		} else {
			datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), "0")
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), ".")
		}

		GoOutDaysFloat64 := cast.ToFloat64(datemap["GoOutDays"]) / 3600 / 8
		//datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
		if GoOutDaysFloat64 == 0 {
			datemap["GoOutDays"] = 0
		} else {
			datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), "0")
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), ".")
		}

		Vac10Float64 := cast.ToFloat64(datemap["Vac10"]) / 3600 / 8
		//datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
		if Vac10Float64 == 0 {
			datemap["Vac10"] = 0
		} else {
			datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), "0")
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), ".")
		}

		//异常天数
		AbnormalDate := cast.ToString(datemap["AbnormalDate"])
		if len(AbnormalDate) > 0 {
			AbnormalDate = strings.TrimRight(AbnormalDate, string(AbnormalDate[len(AbnormalDate)-1]))
			AbnormalDateMap := strings.Split(AbnormalDate, "/")
			sort.Strings(AbnormalDateMap)
			datemap["AbnormalDate"] = strings.Join(AbnormalDateMap, "/")
		} else {
			datemap["AbnormalDate"] = ""
		}

		WorkOvertimeDaysFloat := cast.ToFloat64(datemap["WorkOvertimeDays"]) / 3600 / 8
		//datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
		if WorkOvertimeDaysFloat == 0 {
			datemap["WorkOvertimeDays"] = 0
		} else {
			datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), "0")
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), ".")
		}

		OverlapFloat := cast.ToFloat64(datemap["Overlap"]) / 3600 / 8
		datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
		if OverlapFloat == 0 {
			datemap["Overlap"] = 0
		} else {
			datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), "0")
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), ".")
		}

		if cast.ToString(datemap["AbnormalDate"]) == "" && cast.ToInt(datemap["Vac11"]) <= 3 && RecordType == 1 {
			datemap["IsNormal"] = 1
		}
		if RecordType == 3 {
			datemap["IsNormal"] = 0
		}
		if cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac9"]) > 0 ||
			cast.ToFloat64(datemap["Vac8"]) > 0 ||
			cast.ToFloat64(datemap["Vac7"]) > 0 ||
			cast.ToFloat64(datemap["Vac6"]) > 0 ||
			cast.ToFloat64(datemap["Vac5"]) > 0 ||
			cast.ToFloat64(datemap["Vac4"]) > 0 ||
			cast.ToFloat64(datemap["Vac3"]) > 0 {
			datemap["IsNormal"] = 0
		}

		//补卡审批单处理=================================================================================
		repair, err := db.QueryString(fmt.Sprintf("select count(*) as `c` from `repair` where userid = '%s' and  `date` >= %d AND `date` <= %d;", v["userid"], cast.ToInt(jsondata["starttime"]), cast.ToInt(jsondata["endtime"])+86400))
		if err != nil {
			service.ReturnJson(c, 500, err.Error(), gin.H{})
			return
		}
		if len(repair) > 0 {
			datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + cast.ToInt(repair[0]["c"])
		}

		//FiltersData := []FiltersStruct{}
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "record_type",
		//	Value: "2",
		//})
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "sp_status",
		//	Value: "2",
		//})
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "creator",
		//	Value: v["userid"],
		//})
		//ReqData3 := ReqData3Struct{
		//	Starttime: cast.ToInt(jsondata["starttime"]),
		//	Endtime:   cast.ToInt(jsondata["starttime"]) + 86400*31,
		//	NewCursor: "",
		//	Size:      100,
		//	Filters:   FiltersData,
		//}
		//b3, err := json.Marshal(&ReqData3)
		//if err != nil {
		//	service.ReturnJson(c, 500, err.Error(), gin.H{})
		//	return
		//}
		//datas3, err := utils.GetApprovalInfoData(b3)
		//datemap["Vac11"] = cast.ToInt(len(datas3.SpNoList))
		//=====================================================================================

		datemapbyte, _ := json.Marshal(datemap)
		listdata[k]["clockin"] = string(datemapbyte)
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{
		"list":  listdata,
		"total": cast.ToInt(countdata[0]["total"]),
	})
}

func (clockin Clockin) DetailedList(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), cast.ToInt(jsondata["page_size"]))
	orderstr := " order by a.`userid` desc"

	wheresql := strings.Builder{}

	if cast.ToString(jsondata["staff"]) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(jsondata["staff"])+"%"))
	}
	if cast.ToString(jsondata["department"]) != "" {
		department, err := db.QueryString(fmt.Sprintf("select * from `department` where `id` = %s limit 1", cast.ToString(jsondata["department"])))
		if err != nil {
			service.ReturnJson(c, 500, err.Error(), gin.H{})
			return
		}
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", department[0]["relationship"]+"%"))
	} else {
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-1-79%"))
	}

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	countsql := fmt.Sprintf("select count(*) as total from `staff` as a left join department b on a.main_department = b.id where 1=1 %s", wheresql.String())
	countdata, err := db.QueryString(countsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(jsondata["starttime"]),
		Endtime:    cast.ToInt(jsondata["endtime"]),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type ReqData2Struct struct {
		Opencheckindatatype int      `json:"opencheckindatatype"`
		Starttime           int      `json:"starttime"`
		Endtime             int      `json:"endtime"`
		Useridlist          []string `json:"useridlist"`
	}
	ReqData2 := ReqData2Struct{
		Opencheckindatatype: 3,
		Starttime:           cast.ToInt(jsondata["starttime"]),
		Endtime:             cast.ToInt(jsondata["endtime"]) + 86400*2,
		Useridlist:          usermap,
	}
	b2, err := json.Marshal(&ReqData2)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	datas2, err := utils.CheckinGetcheckindata(b2)

	type datemapStruct struct {
		Date             string `json:"date"`
		Weekday          string `json:"weekday"`
		AbsenteeismNotes string `json:"absenteeism_notes"`
		RecordStatus     string `json:"record_status"`
		TestData         string `json:"testdata"`
	}
	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海

	for k, v := range listdata {
		datemap := []datemapStruct{}

		for _, vv := range datas.Datas {
			if vv.BaseInfo.Acctid == v["userid"] {
				//过年放假
				if vv.BaseInfo.RecordType == 1 && (vv.BaseInfo.Date == 1707408000 || vv.BaseInfo.Date == 1708185600) {
					continue
				}

				//入职判断
				employment := v["employment"]
				if employment != "" {
					employmenttimeStamp, _ := time.ParseInLocation("2006-01-02", employment, cstSh)
					employmenttimeStampUnix := cast.ToInt64(employmenttimeStamp.Unix())
					if cast.ToInt64(vv.BaseInfo.Date) < employmenttimeStampUnix {
						continue
					}
				}

				//时间格式化
				t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				datestr := t.Format("2006/01/02")
				fmt.Println("============= 日期：", datestr)

				if vv.BaseInfo.RecordType == 3 {
					for kkk, vvv := range datas2.Checkindata {
						CheckinTime := time.Unix(cast.ToInt64(vvv.CheckinTime), 0).In(cstSh).Format("15:04")
						CheckinTimeSec := 0
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[0], "0")) * 3600
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[1], "0")) * 60
						if CheckinTimeSec < 14400 {
							datas2.Checkindata[kkk].SchCheckinTime = vvv.CheckinTime - CheckinTimeSec - 60
							fmt.Println("========== 转接时间", vvv.CheckinTime-CheckinTimeSec-60, vvv.CheckinTime, CheckinTimeSec)
						}
					}
				}

				WorkTime := []string{}
				for i := 0; i < len(datas2.Checkindata); i++ {
					if datas2.Checkindata[i].Userid == vv.BaseInfo.Acctid {
						SchCheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].SchCheckinTime), 0).In(cstSh)
						if datestr == SchCheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
							CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
							WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
						}
					}
				}

				//最早时间  最晚时间读取打卡记录
				if len(WorkTime) > 0 {
					startWorkTimeSec := 0
					endWorkTimeSec := 0

					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[0], "0")) * 3600
					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[1], "0")) * 60
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[0], "0")) * 3600
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[1], "0")) * 60

					if len(WorkTime) == 1 {
						vv.SummaryInfo.CheckinCount = 1
					} else if len(WorkTime) >= 2 {
						vv.SummaryInfo.CheckinCount = 2
					}

					if endWorkTimeSec < startWorkTimeSec {
						endWorkTimeSec = endWorkTimeSec + 86400
					}

					vv.SummaryInfo.RegularWorkSec = endWorkTimeSec - startWorkTimeSec
					vv.SummaryInfo.EarliestTime = startWorkTimeSec
					vv.SummaryInfo.LastestTime = endWorkTimeSec
				}

				RecordStatus := ""
				AbsenteeismNotes := ""

				//固定上下班
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					checkin := []string{clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec), clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)}
					checkin1 := []int{0, 0}
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[0], "0")) * 3600
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[1], "0")) * 60
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[0], "0")) * 3600
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[1], "0")) * 60
					fmt.Println("============= 今日通勤", checkin1[1]-checkin1[0])

					//时间日志
					arr := [][]string{}
					arr = append(arr, []string{clockin.SecondToHours(vv.SummaryInfo.EarliestTime), clockin.SecondToHours(vv.SummaryInfo.LastestTime)}) //打卡时间

					//弹性是否关闭
					isElastic := true

					//追加请假时间节点
					if len(vv.HolidayInfos) > 0 {
						for _, vvv := range vv.HolidayInfos {
							fmt.Println(vvv)
							if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "产假") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "加班") {

							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "年假") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "事假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								//fmt.Println("====== 值", DescriptionStart)
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							} else {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							}
							//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							//arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
						}
					}

					fmt.Println("============= 时间节点")
					fmt.Println(arr)

					//时间重写
					arr1 := [][]int{}
					for i := 0; i < len(arr); i++ {
						var q, w int
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[0], "0")) * 3600
						q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[1], "0")) * 60
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[0], "0")) * 3600
						w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[1], "0")) * 60
						arr1 = append(arr1, []int{q, w})
					}

					//进行排序
					sort.Slice(arr1, func(i, j int) bool {
						return arr1[i][0] < arr1[j][0]
					})
					//判断重叠与非重叠
					r, n := clockin.IsTimeCross(arr1)
					arr2 := []int{}
					for _, v := range arr1 {
						for _, vv := range v {
							arr2 = append(arr2, vv)
						}
					}
					sort.Ints(arr2)

					if vv.BaseInfo.RecordType == 1 { //固定班次弹性处理逻辑
						if arr2[0] > 32400 && arr2[0] <= 34200 && isElastic == true { //弹性
							i := 66600 + (arr2[0] - 32400)
							if arr2[len(arr2)-1] >= i {
								arr2[len(arr2)-1] = 66600 + (arr2[0] - 32400)
							} else {
								arr2[len(arr2)-1] = arr2[len(arr2)-1]
							}
						} else {
							arr2[len(arr2)-1] = 66600 //固定6点半
						}
					}

					if r {
						fmt.Println("今日通勤true", arr2[len(arr2)-1], arr2[0], arr2[len(arr2)-1]-arr2[0]) //差值
					} else {
						fmt.Println("今日通勤false", arr2[len(arr2)-1], arr2[0], n, arr2[len(arr2)-1]-arr2[0]-n) //非差值
					}

					if (vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3) && len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.CheckinCount == 2 {
							balance := 0
							if r {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0])
							} else {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0] - n)
							}
							fmt.Println("============= balance")
							fmt.Println(balance)

							if balance <= 0 {
								RecordStatus = "正常"
								AbsenteeismNotes = ""
							} else if balance > 0 && balance <= 1800 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5小时"
							} else if balance > 1800 && balance <= 3600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1小时"
							} else if balance > 3600 && balance <= 5400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1.5小时"
							} else if balance > 5400 && balance <= 7200 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工2小时"
							} else if balance > 7200 && balance <= 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							} else if balance > 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 52200 { //
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 39600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							}
						}

						if vv.SummaryInfo.CheckinCount <= 1 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					}
				}

				if vv.BaseInfo.RecordType == 4 {
					RecordStatus = "正常"
				}

				if vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && RecordStatus == "" {
						RecordStatus = "休息"
					}
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec && vv.SummaryInfo.RegularWorkSec >= 28800 {
							RecordStatus = "正常"
						}
					}
				}

				if vv.BaseInfo.RecordType == 5 && len(vv.BaseInfo.RuleInfo.Checkintime) == 0 && vv.SummaryInfo.CheckinCount > 0 && RecordStatus == "" {
					RecordStatus = "加班"
				}

				for _, vvv := range vv.SpItems {
					if vvv.Type == 1 && vvv.Duration > 0 {
						//AbsenteeismNotes = ""
						//fmt.Println("======================= 请假统计")
						//fmt.Println("日期：", datestr)
						//fmt.Println("vvv:", vvv)

						if RecordStatus == "正常" {
							RecordStatus = ""
						}
						duration := 0.00
						timeType := ""
						if vvv.TimeType == 0 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
							timeType = "天"
						} else if vvv.TimeType == 1 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
							timeType = "小时"
						}
						RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)

						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 && vvv.TimeType == 0 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 28800 && vvv.TimeType == 1 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 28800 && vvv.TimeType == 1 && vvv.Name == "事假" {
							RecordStatus = "事假"
						}
						if vvv.Duration == 28800 && vvv.TimeType == 1 && vvv.Name == "年假" {
							RecordStatus = "年假"
						}
						if vvv.Duration == 86400 && vvv.TimeType == 0 && vvv.Name == "调休假" {
							RecordStatus = "调休"
						}
						if vvv.Duration+vv.SummaryInfo.RegularWorkSec >= 28800 && vvv.VacationId == 12 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 2 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("补卡")
					}
					if vvv.Type == 3 && vvv.Count > 0 { //出差
						RecordStatus = fmt.Sprintf("%s", vvv.Name)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}
						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 86400 && vvv.TimeType == 0 && vvv.Name == "出差" {
							RecordStatus = "出差"
						}
					}
					if vvv.Type == 4 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}
						if vvv.Duration == 28800 {
							AbsenteeismNotes = ""
							RecordStatus = "正常"
						}
					}
					if vvv.Type == 100 && vvv.Count > 0 {
						RecordStatus += fmt.Sprintf("%s", vvv.Name)
					}
				}

				TestData := ""
				datemapbyte, _ := json.Marshal(vv)
				TestData = string(datemapbyte)

				datemap = append(datemap, datemapStruct{
					Date:             datestr,
					Weekday:          weekDayString(vv.BaseInfo.Date),
					AbsenteeismNotes: AbsenteeismNotes,
					RecordStatus:     RecordStatus,
					TestData:         TestData,
				})
			}
		}
		datemapbyte, _ := json.Marshal(datemap)
		listdata[k]["clockin"] = string(datemapbyte)
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{
		"list":  listdata,
		"total": cast.ToInt(countdata[0]["total"]),
	})
}

func (clockin Clockin) StatisticsExport(row_cell int, page_index int, page_size int, staff string, department string, starttime int, endtime int, ExportId string) (c int, arow int, e error) {
	var err error

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(page_index)-1)*cast.ToInt(page_size), cast.ToInt(page_size))
	orderstr := " order by a.`userid` asc"

	wheresql := strings.Builder{}

	if cast.ToString(staff) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(staff)+"%"))
	}
	if cast.ToString(department) != "" {
		relationship, err := db.QueryString(fmt.Sprintf("select relationship from department where id = %s limit 1", department))
		if err != nil {
			return 0, 0, err
		}
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", relationship[0]["relationship"]+"%"))
	} else {
		wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-1-79%"))
	}

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		return 0, 0, err
	}
	if len(listdata) == 0 {
		return 0, 0, err
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(starttime),
		Endtime:    cast.ToInt(endtime),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		return 0, 0, err
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type datemapStruct struct {
		Date             string `json:"date"`
		Weekday          string `json:"weekday"`
		AbsenteeismNotes string `json:"absenteeism_notes"`
		RecordStatus     string `json:"record_status"`
		TestData         string `json:"testdata"`
	}

	type ReqData2Struct struct {
		Opencheckindatatype int      `json:"opencheckindatatype"`
		Starttime           int      `json:"starttime"`
		Endtime             int      `json:"endtime"`
		Useridlist          []string `json:"useridlist"`
	}
	ReqData2 := ReqData2Struct{
		Opencheckindatatype: 3,
		Starttime:           cast.ToInt(starttime),
		Endtime:             cast.ToInt(endtime) + 86400*2,
		Useridlist:          usermap,
	}
	b2, err := json.Marshal(&ReqData2)
	if err != nil {
		return 0, 0, err
	}
	datas2, err := utils.CheckinGetcheckindata(b2)

	////审批单统计补卡
	//type FiltersStruct struct {
	//	Key   string `json:"key"`
	//	Value string `json:"value"`
	//}
	//type ReqData3Struct struct {
	//	Starttime int             `json:"starttime"`
	//	Endtime   int             `json:"endtime"`
	//	NewCursor string          `json:"new_cursor"`
	//	Size      int             `json:"size"`
	//	Filters   []FiltersStruct `json:"filters"`
	//}

	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海

	destinationPath := fmt.Sprintf("./StatisticsExportTemplate_%s.xlsx", ExportId)
	xlsx, err := excelize.OpenFile(destinationPath)
	if err != nil {
		return 0, 0, err
	}

	dStime := time.Unix(cast.ToInt64(starttime), 0).In(cstSh)
	dStimeStr := dStime.Format("2006/01/02")
	eEtime := time.Unix(cast.ToInt64(endtime), 0).In(cstSh)
	eEtimeStr := eEtime.Format("2006/01/02")

	days := (cast.ToInt(endtime) + 86400 - cast.ToInt(starttime)) / 86400

	arow = 0

	for _, v := range listdata {
		datemap := make(map[string]interface{})
		datemap["Days"] = days           //总天数
		datemap["TotalDays"] = 0         //排班总天数
		datemap["BusinessTripsDays"] = 0 //出差次数
		datemap["GoOutDays"] = 0         //外勤次数
		datemap["WorkOvertimeDays"] = 0  //加班天数
		datemap["OnDutyDays"] = 0        //在岗时间
		datemap["Vac1"] = 0              //年休假
		datemap["Vac2"] = 0              //调休假
		datemap["Vac3"] = 0              //事假
		datemap["Vac4"] = 0              //病假
		datemap["Vac5"] = 0              //工伤假(没有)
		datemap["Vac6"] = 0              //产假
		datemap["Vac7"] = 0              //产检假
		datemap["Vac8"] = 0              //婚假
		datemap["Vac9"] = 0              //丧假
		datemap["Vac10"] = 0             //育儿假
		datemap["Vac11"] = 0             //补卡次数
		datemap["CheckInDays"] = 0       //打卡天数
		datemap["GoOutWelfare"] = 0      //外出补助次数
		datemap["DinnerWelfare"] = 0     //晚餐补助次数
		datemap["NightSnackWelfare"] = 0 //夜宵补助次数
		datemap["AbnormalDate"] = ""     //异常日期
		datemap["AbsenteeismDays"] = 0   //旷工天数
		datemap["IsNormal"] = 0          //是否全勤
		datemap["Overlap"] = 0           //考勤重叠

		datemap["C"] = ""
		datemap["D"] = fmt.Sprintf("%s-%s", dStimeStr, eEtimeStr)

		RecordType := 0
		for i := 0; i < len(datas.Datas); i++ {
			if datas.Datas[i].BaseInfo.Acctid == v["userid"] {
				RecordType = datas.Datas[i].BaseInfo.RecordType
			}
		}

		for _, vv := range datas.Datas {
			if vv.BaseInfo.Acctid == v["userid"] {
				datemap["C"] = vv.BaseInfo.DepartsName
				//时间格式化
				t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				datestr := t.Format("2006/01/02")
				fmt.Println(datestr)

				//在岗时间
				if vv.SummaryInfo.RegularWorkSec > 0 {
					datemap["OnDutyDays"] = cast.ToInt(datemap["OnDutyDays"]) + vv.SummaryInfo.RegularWorkSec
				}

				if vv.BaseInfo.RecordType == 3 {
					for kkk, vvv := range datas2.Checkindata {
						CheckinTime := time.Unix(cast.ToInt64(vvv.CheckinTime), 0).In(cstSh).Format("15:04")
						CheckinTimeSec := 0
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[0], "0")) * 3600
						CheckinTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(CheckinTime, ":")[1], "0")) * 60
						if CheckinTimeSec < 14400 {
							datas2.Checkindata[kkk].SchCheckinTime = vvv.CheckinTime - CheckinTimeSec - 60
							fmt.Println("========== 转接时间", vvv.CheckinTime-CheckinTimeSec-60, vvv.CheckinTime, CheckinTimeSec)
						}
					}
				}

				//isAddKey := 0
				WorkTime := []string{}
				for i := 0; i < len(datas2.Checkindata); i++ {
					if datas2.Checkindata[i].Userid == vv.BaseInfo.Acctid {
						if datas2.Checkindata[i].SchCheckinTime > 0 {
							SchCheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].SchCheckinTime), 0).In(cstSh)
							if datestr == SchCheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						} else {
							CheckinTime := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
							if datestr == CheckinTime.Format("2006/01/02") && datas2.Checkindata[i].ExceptionType != "未打卡" {
								//isAddKey = i
								CheckinTimet := time.Unix(cast.ToInt64(datas2.Checkindata[i].CheckinTime), 0).In(cstSh)
								WorkTime = append(WorkTime, CheckinTimet.Format("15:04"))
							}
						}
					}
				}

				//最早时间  最晚时间读取打卡记录
				if len(WorkTime) > 0 {
					startWorkTimeSec := 0
					endWorkTimeSec := 0

					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[0], "0")) * 3600
					startWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[0], ":")[1], "0")) * 60
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[0], "0")) * 3600
					endWorkTimeSec += cast.ToInt(strings.TrimLeft(strings.Split(WorkTime[len(WorkTime)-1], ":")[1], "0")) * 60

					if len(WorkTime) == 1 {
						vv.SummaryInfo.CheckinCount = 1
					} else if len(WorkTime) >= 2 {
						vv.SummaryInfo.CheckinCount = 2
					}

					if endWorkTimeSec < startWorkTimeSec {
						endWorkTimeSec = endWorkTimeSec + 86400
					}

					vv.SummaryInfo.RegularWorkSec = endWorkTimeSec - startWorkTimeSec
					vv.SummaryInfo.EarliestTime = startWorkTimeSec
					vv.SummaryInfo.LastestTime = endWorkTimeSec
				}

				//if datas2.Checkindata[isAddKey].Deviceid == "" && datas2.Checkindata[isAddKey].Wifiname == "" {
				//	isAdd := 1
				//	if len(vv.HolidayInfos) > 0 {
				//		for _, vvv := range vv.HolidayInfos {
				//			for _, vvvv := range vvv.SpTitle.Data {
				//				if strings.Contains(vvvv.Text, "补卡") {
				//					isAdd = 0
				//				}
				//			}
				//		}
				//	}
				//	if isAdd == 1 {
				//		datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + 1
				//	}
				//}

				//入职判断
				employment := v["employment"]
				if employment != "" {
					employmenttimeStamp, _ := time.ParseInLocation("2006-01-02", employment, cstSh)
					employmenttimeStampUnix := cast.ToInt64(employmenttimeStamp.Unix())
					if cast.ToInt64(vv.BaseInfo.Date) < employmenttimeStampUnix {
						continue
					}
				}

				//排班天数
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
				}

				//过年放假
				if vv.BaseInfo.RecordType == 1 && (vv.BaseInfo.Date == 1707408000 || vv.BaseInfo.Date == 1708185600) {
					datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) - 1
					continue
				}

				//======

				for _, vvv := range vv.SpItems {
					if vvv.Duration >= 86400 {
						vvv.Duration = 28800
					}
					if vvv.Type == 1 && vvv.VacationId == 1 && vvv.Duration > 0 {
						datemap["Vac1"] = cast.ToFloat64(datemap["Vac1"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 4 && vvv.Duration > 0 {
						var duration float64
						if vvv.TimeType == 0 { //天
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400) * cast.ToFloat64(28800)
						} else if vvv.TimeType == 1 { //小时

						}
						datemap["Vac2"] = cast.ToFloat64(datemap["Vac2"]) + duration
					}
					if vvv.Type == 1 && vvv.VacationId == 2 && vvv.Duration > 0 {
						datemap["Vac3"] = cast.ToFloat64(datemap["Vac3"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 3 && vvv.Duration > 0 {
						var duration float64
						if vvv.TimeType == 0 { //天
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400) * cast.ToFloat64(28800)
						} else if vvv.TimeType == 1 { //小时

						}
						datemap["Vac4"] = cast.ToFloat64(datemap["Vac4"]) + duration
					}
					if vvv.Type == 1 && vvv.VacationId == 6 && vvv.Duration > 0 {
						datemap["Vac6"] = cast.ToFloat64(datemap["Vac6"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 11 && vvv.Duration > 0 {
						datemap["Vac7"] = cast.ToFloat64(datemap["Vac7"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 5 && vvv.Duration > 0 {
						datemap["Vac8"] = cast.ToFloat64(datemap["Vac8"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 9 && vvv.Duration > 0 {
						datemap["Vac9"] = cast.ToFloat64(datemap["Vac9"]) + cast.ToFloat64(vvv.Duration)
					}
					if vvv.Type == 1 && vvv.VacationId == 12 && vvv.Duration > 0 {
						datemap["Vac10"] = cast.ToFloat64(datemap["Vac10"]) + cast.ToFloat64(vvv.Duration)
					}
				}

				AbsenteeismNotes := ""
				RecordStatus := ""

				if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 {
					fmt.Println("============================ 打卡天数", datestr)
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
				}

				if len(vv.HolidayInfos) > 0 {
					for _, vvv := range vv.HolidayInfos {
						if strings.Contains(vvv.SpTitle.Data[0].Text, "加班") {
							datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {
							datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + 1
						} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
							DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							DescriptionStartSec := 0
							DescriptionEndSec := 0
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
							DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
							DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
							if DescriptionEndSec-DescriptionStartSec >= 14400 {
								datemap["GoOutWelfare"] = cast.ToInt(datemap["GoOutWelfare"]) + 1
							}
							if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 && DescriptionEndSec-DescriptionStartSec >= 14400 {
								datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) - 1
							}
							for _, vvv := range vv.SpItems {
								if vvv.Type == 4 && vvv.Duration > 0 {
									datemap["GoOutDays"] = cast.ToInt(datemap["GoOutDays"]) + vvv.Duration
								}
							}
						}
					}
				}

				//固定上下班
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
					checkin := []string{clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec), clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)}
					checkin1 := []int{0, 0}
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[0], "0")) * 3600
					checkin1[0] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[0], ":")[1], "0")) * 60
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[0], "0")) * 3600
					checkin1[1] += cast.ToInt(strings.TrimLeft(strings.Split(checkin[1], ":")[1], "0")) * 60
					fmt.Println("============= 今日通勤", checkin1[1]-checkin1[0])

					//时间日志
					arr := [][]string{}
					arr = append(arr, []string{clockin.SecondToHours(vv.SummaryInfo.EarliestTime), clockin.SecondToHours(vv.SummaryInfo.LastestTime)}) //打卡时间

					//弹性是否关闭
					isElastic := true

					//追加请假时间节点
					if len(vv.HolidayInfos) > 0 {
						for _, vvv := range vv.HolidayInfos {
							fmt.Println(vvv)
							if strings.Contains(vvv.SpTitle.Data[0].Text, "年假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								if DescriptionStart == "14:00" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}

								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "事假") {
								if strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1] == "09:30" {
									isElastic = false
								}
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionEnd == "12:30" {
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "外出") {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]

								if DescriptionStart == "14:00" {
									fmt.Println("============================= 外出外出补充时间")
									arr = append(arr, []string{"12:30", "14:00"}) //打卡时间
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}

								DescriptionStartSec := 0
								DescriptionEndSec := 0
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[0], "0")) * 3600
								DescriptionStartSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionStart, ":")[1], "0")) * 60
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[0], "0")) * 3600
								DescriptionEndSec += cast.ToInt(strings.TrimLeft(strings.Split(DescriptionEnd, ":")[1], "0")) * 60
								//if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 14400 && DescriptionEndSec-DescriptionStartSec >= 14400 {
								//	datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) - 1
								//}
								//重叠时间
								if vv.SummaryInfo.LastestTime-vv.SummaryInfo.EarliestTime > 0 && DescriptionEndSec-DescriptionStartSec > 0 {
									overlap := [][]int{}
									overlap = append(overlap, []int{vv.SummaryInfo.EarliestTime, vv.SummaryInfo.LastestTime})
									overlap = append(overlap, []int{DescriptionStartSec, DescriptionEndSec})
									sort.Slice(overlap, func(i, j int) bool {
										return overlap[i][0] < overlap[j][0]
									})
									overlapStart := math.Max(cast.ToFloat64(overlap[0][0]), cast.ToFloat64(overlap[1][0]))
									overlapEnd := math.Min(cast.ToFloat64(overlap[0][1]), cast.ToFloat64(overlap[1][1]))
									if cast.ToInt(overlapEnd) > cast.ToInt(overlapStart) {
										datemap["Overlap"] = cast.ToInt(datemap["Overlap"]) + (cast.ToInt(overlapEnd) - cast.ToInt(overlapStart))
									}
									fmt.Println("========== 重叠时间", cast.ToInt(overlapEnd), cast.ToInt(overlapStart), cast.ToInt(overlapEnd)-cast.ToInt(overlapStart))
								}
							} else if strings.Contains(vvv.SpTitle.Data[0].Text, "补卡") {

							} else {
								DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
								DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
								if DescriptionStart == "上午" && DescriptionEnd == "上午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].WorkSec)
								}
								if DescriptionStart == "下午" && DescriptionEnd == "下午" {
									DescriptionStart = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[0].OffWorkSec)
									DescriptionEnd = clockin.SecondToHours(vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
								}
								if DescriptionStart != "上午" && DescriptionEnd != "下午" {
									arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
								}
							}
							//DescriptionStart := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[0], " ")[1]
							//DescriptionEnd := strings.Split(strings.Split(vvv.SpDescription.Data[0].Text, " - ")[1], " ")[1]
							//arr = append(arr, []string{DescriptionStart, DescriptionEnd}) //打卡时间
						}
					}

					fmt.Println("============= 时间节点")
					fmt.Println(arr)

					//时间重写
					arr1 := [][]int{}
					for i := 0; i < len(arr); i++ {
						var q, w int
						if strings.Split(arr[i][0], ":")[0] != "上午" && strings.Split(arr[i][0], ":")[0] != "下午" {
							q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[0], "0")) * 3600
							q += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][0], ":")[1], "0")) * 60
							w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[0], "0")) * 3600
							w += cast.ToInt(strings.TrimLeft(strings.Split(arr[i][1], ":")[1], "0")) * 60
							arr1 = append(arr1, []int{q, w})
						}
					}

					//进行排序
					sort.Slice(arr1, func(i, j int) bool {
						return arr1[i][0] < arr1[j][0]
					})
					//判断重叠与非重叠
					r, n := clockin.IsTimeCross(arr1)
					arr2 := []int{}
					for _, v := range arr1 {
						for _, vv := range v {
							arr2 = append(arr2, vv)
						}
					}
					sort.Ints(arr2)

					if vv.BaseInfo.RecordType == 1 { //固定班次弹性处理逻辑
						if arr2[0] > 32400 && arr2[0] <= 34200 && isElastic == true { //弹性
							i := 66600 + (arr2[0] - 32400)
							if arr2[len(arr2)-1] >= i {
								arr2[len(arr2)-1] = 66600 + (arr2[0] - 32400)
							} else {
								arr2[len(arr2)-1] = arr2[len(arr2)-1]
							}
						} else {
							arr2[len(arr2)-1] = 66600 //固定6点半
						}
					}

					if r {
						fmt.Println("今日通勤true", n, arr2[len(arr2)-1], arr2[0], arr2[len(arr2)-1]-arr2[0]) //差值
					} else {
						fmt.Println("今日通勤false", arr2[len(arr2)-1], arr2[0], n, arr2[len(arr2)-1]-arr2[0]-n) //非差值
					}

					if (vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3) && len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.CheckinCount == 2 {
							balance := 0
							if r {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0])
							} else {
								balance = (checkin1[1] - checkin1[0]) - (arr2[len(arr2)-1] - arr2[0] - n)
							}
							fmt.Println("============= balance")
							fmt.Println(balance)

							if balance <= 0 {
								RecordStatus = "正常"
								AbsenteeismNotes = ""
							} else if balance > 0 && balance <= 1800 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5小时"
							} else if balance > 1800 && balance <= 3600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1小时"
							} else if balance > 3600 && balance <= 5400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1.5小时"
							} else if balance > 5400 && balance <= 7200 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工2小时"
							} else if balance > 7200 && balance <= 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							} else if balance > 14400 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 52200 { //
								RecordStatus = ""
								AbsenteeismNotes = "旷工1天"
							} else if vv.SummaryInfo.EarliestTime >= 39600 {
								RecordStatus = ""
								AbsenteeismNotes = "旷工0.5天"
							}
						}

						if vv.SummaryInfo.CheckinCount <= 1 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					}
				}

				for _, vvv := range vv.SpItems {
					if vvv.Type == 1 && vvv.Duration > 0 {

						if RecordStatus == "正常" {
							RecordStatus = ""
						}
						duration := 0.00
						timeType := ""
						if vvv.TimeType == 0 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
							timeType = "天"
						} else if vvv.TimeType == 1 {
							duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
							timeType = "小时"
						}
						RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)
						if AbsenteeismNotes != "" {
							RecordStatus = ""
						}

						if vvv.Duration == 86400 && vvv.TimeType == 0 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration == 28800 && vvv.TimeType == 1 {
							AbsenteeismNotes = ""
						}

						if vvv.Duration+vv.SummaryInfo.RegularWorkSec >= 28800 && vvv.VacationId == 12 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 2 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("补卡")
					}
					if vvv.Type == 3 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 86400 {
							AbsenteeismNotes = ""
						}

						Duration := 0
						if vvv.Duration >= 86400 {
							Duration += 28800
						} else {
							Duration = vvv.Duration
						}
						if vvv.TimeType == 0 {
							DurationSec := cast.ToFloat64(vvv.Duration) / 86400 * 28800
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + cast.ToInt(DurationSec)
						} else {
							datemap["BusinessTripsDays"] = cast.ToInt(datemap["BusinessTripsDays"]) + (Duration)
						}

					}
					if vvv.Type == 4 && vvv.Count > 0 {
						RecordStatus = fmt.Sprintf("%s", vvv.Name)

						if vvv.Duration == 28800 {
							AbsenteeismNotes = ""
						}
					}
					if vvv.Type == 100 && vvv.Count > 0 {
						RecordStatus += fmt.Sprintf("%s", vvv.Name)
					}
				}

				if vv.BaseInfo.RecordType == 4 {
					RecordStatus = "正常"
				}

				if vv.BaseInfo.RecordType == 1 || vv.BaseInfo.RecordType == 3 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) <= 0 && RecordStatus == "" {
						RecordStatus = "休息"
					}
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						if vv.SummaryInfo.EarliestTime <= vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec && vv.SummaryInfo.LastestTime >= vv.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec && vv.SummaryInfo.RegularWorkSec >= 28800 {
							RecordStatus = "正常"
						}
					}
				}

				if vv.BaseInfo.RecordType == 5 && len(vv.BaseInfo.RuleInfo.Checkintime) == 0 && vv.SummaryInfo.CheckinCount > 0 && RecordStatus == "" {
					RecordStatus = "加班"
				}

				//免打卡班次
				if vv.BaseInfo.RecordType == 4 {
					if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
						datemap["TotalDays"] = cast.ToInt(datemap["TotalDays"]) + 1
					}
					datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
					datemap["AbsenteeismDays"] = 0
					datemap["AbnormalDate"] = ""
					datemap["IsNormal"] = 1
					continue
				}

				//加班天数
				//if vv.OtInfo.OtStatus == 1 && vv.OtInfo.OtDuration > 0 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.OtInfo.OtDuration
				//}
				//if vv.BaseInfo.RecordType == 5 {
				//	datemap["WorkOvertimeDays"] = cast.ToInt(datemap["WorkOvertimeDays"]) + vv.SummaryInfo.RegularWorkSec
				//}

				//晚餐补助(正常)
				//t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
				a := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b, _ := time.ParseInLocation("2006-01-02 15:04:05", a, cstSh)
				c := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d, _ := time.ParseInLocation("2006-01-02 15:04:05", c, cstSh)
				e := b.Unix() - d.Unix()
				if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 && vv.SummaryInfo.EarliestTime <= 66600 {
					if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e) {
						datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
					}
				}

				//晚餐补助(直播)
				//a2 := fmt.Sprintf("%s-%s-%s 20:30:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//b2, _ := time.ParseInLocation("2006-01-02 15:04:05", a2, cstSh)
				//c2 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				//d2, _ := time.ParseInLocation("2006-01-02 15:04:05", c2, cstSh)
				//e2 := b2.Unix() - d2.Unix()
				//if len(vv.BaseInfo.RuleInfo.Checkintime) > 0 {
				//	if vv.BaseInfo.RecordType == 3 && strings.Index(vv.BaseInfo.RuleInfo.Groupname, "直播") > -1 && vv.BaseInfo.RuleInfo.Checkintime[0].WorkSec <= 66600 && vv.SummaryInfo.LastestTime >= cast.ToInt(e2) {
				//		datemap["DinnerWelfare"] = cast.ToInt(datemap["DinnerWelfare"]) + 1
				//	}
				//}

				//宵夜补助 超过 23:00
				a1 := fmt.Sprintf("%s-%s-%s 23:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				b1, _ := time.ParseInLocation("2006-01-02 15:04:05", a1, cstSh)
				c1 := fmt.Sprintf("%s-%s-%s 00:00:00", t.Format("2006"), t.Format("01"), t.Format("02"))
				d1, _ := time.ParseInLocation("2006-01-02 15:04:05", c1, cstSh)
				e1 := b1.Unix() - d1.Unix()
				if vv.BaseInfo.RecordType == 1 && vv.SummaryInfo.LastestTime >= cast.ToInt(e1) {
					datemap["NightSnackWelfare"] = cast.ToInt(datemap["NightSnackWelfare"]) + 1
				}

				if AbsenteeismNotes != "" {
					t := time.Unix(cast.ToInt64(vv.BaseInfo.Date), 0).In(cstSh)
					datestr := t.Format("02")
					datemap["AbnormalDate"] = cast.ToString(datemap["AbnormalDate"]) + datestr + "/"
				}

				if AbsenteeismNotes == "旷工0.5小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 1800
				} else if AbsenteeismNotes == "旷工1小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 3600
				} else if AbsenteeismNotes == "旷工1.5小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 5400
				} else if AbsenteeismNotes == "旷工2小时" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 7200
				} else if AbsenteeismNotes == "旷工0.5天" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 14400
				} else if AbsenteeismNotes == "旷工1天" {
					datemap["AbsenteeismDays"] = cast.ToInt(datemap["AbsenteeismDays"]) + 28800
				}

				//if vv.SummaryInfo.RegularWorkSec > 14400 {
				//	datemap["CheckInDays"] = cast.ToInt(datemap["CheckInDays"]) + 1
				//}
			}
		}

		OnDutyDaysFloat := cast.ToFloat64(datemap["OnDutyDays"]) + cast.ToFloat64(datemap["BusinessTripsDays"]) + cast.ToFloat64(datemap["GoOutDays"])
		OnDutyDaysFloat = OnDutyDaysFloat / 3600 / 8
		datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
		if OnDutyDaysFloat == 0 {
			datemap["OnDutyDays"] = 0
		} else {
			datemap["OnDutyDays"] = fmt.Sprintf("%.4f", OnDutyDaysFloat)
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), "0")
			datemap["OnDutyDays"] = strings.TrimRight(cast.ToString(datemap["OnDutyDays"]), ".")
		}

		AbsenteeismDaysFloat64 := cast.ToFloat64(datemap["AbsenteeismDays"]) / 3600 / 8
		//datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
		if AbsenteeismDaysFloat64 == 0 {
			datemap["AbsenteeismDays"] = 0
		} else {
			datemap["AbsenteeismDays"] = fmt.Sprintf("%.4f", AbsenteeismDaysFloat64)
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), "0")
			datemap["AbsenteeismDays"] = strings.TrimRight(cast.ToString(datemap["AbsenteeismDays"]), ".")
		}

		Vac1Float64 := cast.ToFloat64(datemap["Vac1"]) / 3600 / 8
		if Vac1Float64 == 0 {
			datemap["Vac1"] = 0
		} else {
			datemap["Vac1"] = fmt.Sprintf("%.4f", Vac1Float64)
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), "0")
			datemap["Vac1"] = strings.TrimRight(cast.ToString(datemap["Vac1"]), ".")
		}

		Vac2Float64 := cast.ToFloat64(datemap["Vac2"]) / 3600 / 8
		//datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
		if Vac2Float64 == 0 {
			datemap["Vac2"] = 0
		} else {
			datemap["Vac2"] = fmt.Sprintf("%.4f", Vac2Float64)
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), "0")
			datemap["Vac2"] = strings.TrimRight(cast.ToString(datemap["Vac2"]), ".")
		}

		Vac3Float64 := cast.ToFloat64(datemap["Vac3"]) / 3600 / 8
		//datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
		if Vac3Float64 == 0 {
			datemap["Vac3"] = 0
		} else {
			datemap["Vac3"] = fmt.Sprintf("%.4f", Vac3Float64)
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), "0")
			datemap["Vac3"] = strings.TrimRight(cast.ToString(datemap["Vac3"]), ".")
		}

		Vac4Float64 := cast.ToFloat64(datemap["Vac4"]) / 3600 / 8
		//datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
		if Vac4Float64 == 0 {
			datemap["Vac4"] = 0
		} else {
			datemap["Vac4"] = fmt.Sprintf("%.4f", Vac4Float64)
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), "0")
			datemap["Vac4"] = strings.TrimRight(cast.ToString(datemap["Vac4"]), ".")
		}

		Vac6Float64 := cast.ToFloat64(datemap["Vac6"]) / 3600 / 8
		//datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
		if Vac6Float64 == 0 {
			datemap["Vac6"] = 0
		} else {
			datemap["Vac6"] = fmt.Sprintf("%.4f", Vac6Float64)
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), "0")
			datemap["Vac6"] = strings.TrimRight(cast.ToString(datemap["Vac6"]), ".")
		}

		Vac7Float64 := cast.ToFloat64(datemap["Vac7"]) / 3600 / 8
		//datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
		if Vac7Float64 == 0 {
			datemap["Vac7"] = 0
		} else {
			datemap["Vac7"] = fmt.Sprintf("%.4f", Vac7Float64)
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), "0")
			datemap["Vac7"] = strings.TrimRight(cast.ToString(datemap["Vac7"]), ".")
		}

		Vac8Float64 := cast.ToFloat64(datemap["Vac8"]) / 3600 / 8
		//datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
		if Vac8Float64 == 0 {
			datemap["Vac8"] = 0
		} else {
			datemap["Vac8"] = fmt.Sprintf("%.4f", Vac8Float64)
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), "0")
			datemap["Vac8"] = strings.TrimRight(cast.ToString(datemap["Vac8"]), ".")
		}

		Vac9Float64 := cast.ToFloat64(datemap["Vac9"]) / 3600 / 8
		//datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
		if Vac9Float64 == 0 {
			datemap["Vac9"] = 0
		} else {
			datemap["Vac9"] = fmt.Sprintf("%.4f", Vac9Float64)
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), "0")
			datemap["Vac9"] = strings.TrimRight(cast.ToString(datemap["Vac9"]), ".")
		}

		BusinessTripsDaysFloat64 := cast.ToFloat64(datemap["BusinessTripsDays"]) / 3600 / 8
		//datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
		if BusinessTripsDaysFloat64 == 0 {
			datemap["BusinessTripsDays"] = 0
		} else {
			datemap["BusinessTripsDays"] = fmt.Sprintf("%.4f", BusinessTripsDaysFloat64)
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), "0")
			datemap["BusinessTripsDays"] = strings.TrimRight(cast.ToString(datemap["BusinessTripsDays"]), ".")
		}

		GoOutDaysFloat64 := cast.ToFloat64(datemap["GoOutDays"]) / 3600 / 8
		//datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
		if GoOutDaysFloat64 == 0 {
			datemap["GoOutDays"] = 0
		} else {
			datemap["GoOutDays"] = fmt.Sprintf("%.4f", GoOutDaysFloat64)
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), "0")
			datemap["GoOutDays"] = strings.TrimRight(cast.ToString(datemap["GoOutDays"]), ".")
		}

		Vac10Float64 := cast.ToFloat64(datemap["Vac10"]) / 3600 / 8
		//datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
		if Vac10Float64 == 0 {
			datemap["Vac10"] = 0
		} else {
			datemap["Vac10"] = fmt.Sprintf("%.4f", Vac10Float64)
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), "0")
			datemap["Vac10"] = strings.TrimRight(cast.ToString(datemap["Vac10"]), ".")
		}

		//异常天数
		AbnormalDate := cast.ToString(datemap["AbnormalDate"])
		if len(AbnormalDate) > 0 {
			AbnormalDate = strings.TrimRight(AbnormalDate, string(AbnormalDate[len(AbnormalDate)-1]))
			AbnormalDateMap := strings.Split(AbnormalDate, "/")
			sort.Strings(AbnormalDateMap)
			datemap["AbnormalDate"] = strings.Join(AbnormalDateMap, "/")
		} else {
			datemap["AbnormalDate"] = ""
		}

		WorkOvertimeDaysFloat := cast.ToFloat64(datemap["WorkOvertimeDays"]) / 3600 / 8
		//datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
		if WorkOvertimeDaysFloat == 0 {
			datemap["WorkOvertimeDays"] = 0
		} else {
			datemap["WorkOvertimeDays"] = fmt.Sprintf("%.4f", WorkOvertimeDaysFloat)
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), "0")
			datemap["WorkOvertimeDays"] = strings.TrimRight(cast.ToString(datemap["WorkOvertimeDays"]), ".")
		}

		OverlapFloat := cast.ToFloat64(datemap["Overlap"]) / 3600 / 8
		datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
		if OverlapFloat == 0 {
			datemap["Overlap"] = 0
		} else {
			datemap["Overlap"] = fmt.Sprintf("%.4f", OverlapFloat)
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), "0")
			datemap["Overlap"] = strings.TrimRight(cast.ToString(datemap["Overlap"]), ".")
		}

		if cast.ToString(datemap["AbnormalDate"]) == "" && cast.ToInt(datemap["Vac11"]) <= 3 && RecordType == 1 {
			datemap["IsNormal"] = 1
		}
		if RecordType == 3 {
			datemap["IsNormal"] = 0
		}
		if cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac10"]) > 0 ||
			cast.ToFloat64(datemap["Vac9"]) > 0 ||
			cast.ToFloat64(datemap["Vac8"]) > 0 ||
			cast.ToFloat64(datemap["Vac7"]) > 0 ||
			cast.ToFloat64(datemap["Vac6"]) > 0 ||
			cast.ToFloat64(datemap["Vac5"]) > 0 ||
			cast.ToFloat64(datemap["Vac4"]) > 0 ||
			cast.ToFloat64(datemap["Vac3"]) > 0 {
			datemap["IsNormal"] = 0
		}

		//补卡审批单处理=================================================================================
		repair, _ := db.QueryString(fmt.Sprintf("select count(*) as `c` from `repair` where userid = '%s' and  `date` >= %d AND `date` <= %d;", v["userid"], cast.ToInt(starttime), cast.ToInt(endtime)+86400))
		if len(repair) > 0 {
			datemap["Vac11"] = cast.ToInt(datemap["Vac11"]) + cast.ToInt(repair[0]["c"])
		}
		//FiltersData := []FiltersStruct{}
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "record_type",
		//	Value: "2",
		//})
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "sp_status",
		//	Value: "2",
		//})
		//FiltersData = append(FiltersData, FiltersStruct{
		//	Key:   "creator",
		//	Value: v["userid"],
		//})
		//ReqData3 := ReqData3Struct{
		//	Starttime: cast.ToInt(starttime),
		//	Endtime:   cast.ToInt(starttime) + 86400*31,
		//	NewCursor: "",
		//	Size:      100,
		//	Filters:   FiltersData,
		//}
		//b3, _ := json.Marshal(&ReqData3)
		//datas3, _ := utils.GetApprovalInfoData(b3)
		//datemap["Vac11"] = cast.ToInt(len(datas3.SpNoList))
		//=====================================================================================

		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("A%d", row_cell), v["userid"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("B%d", row_cell), v["name"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", row_cell), datemap["C"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("D%d", row_cell), datemap["D"])

		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("I%d", row_cell), datemap["Days"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("J%d", row_cell), datemap["TotalDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", row_cell), datemap["CheckInDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("L%d", row_cell), datemap["WorkOvertimeDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("M%d", row_cell), datemap["OnDutyDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("N%d", row_cell), datemap["BusinessTripsDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("O%d", row_cell), datemap["GoOutDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("P%d", row_cell), datemap["GoOutWelfare"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("Q%d", row_cell), datemap["AbsenteeismDays"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("R%d", row_cell), datemap["Overlap"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("S%d", row_cell), datemap["AbnormalDate"])

		IsNormalStr := ""
		if datemap["IsNormal"] == 1 {
			IsNormalStr = "是"
		} else {
			IsNormalStr = "否"
		}
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("T%d", row_cell), IsNormalStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("U%d", row_cell), datemap["Vac1"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("V%d", row_cell), datemap["Vac2"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("W%d", row_cell), datemap["Vac3"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("X%d", row_cell), datemap["Vac4"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("Y%d", row_cell), datemap["Vac6"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("Z%d", row_cell), datemap["Vac7"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AA%d", row_cell), "0")
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AB%d", row_cell), datemap["Vac8"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AC%d", row_cell), datemap["Vac9"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AD%d", row_cell), datemap["Vac10"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AE%d", row_cell), datemap["Vac11"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AF%d", row_cell), datemap["DinnerWelfare"])
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("AG%d", row_cell), datemap["NightSnackWelfare"])

		var adStr, aeStr, afStr, agStr string
		if cast.ToString(datemap["C"]) != "" {
			arrC := strings.Split(strings.Split(cast.ToString(datemap["C"]), ";")[0], "/")

			if len(strings.Split(cast.ToString(datemap["C"]), ";")) > 1 {
				arrD := strings.Split(strings.Split(cast.ToString(datemap["C"]), ";")[1], "/")
				if len(arrD) > len(arrC) {
					arrC = arrD
				}
			}

			for i := 0; i < len(arrC); i++ {
				if i == 2 {
					adStr = arrC[i]
				} else if i == 3 {
					aeStr = arrC[i]
				} else if i == 4 {
					afStr = arrC[i]
				} else if i == 5 {
					agStr = arrC[i]
				}
			}
		}
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("E%d", row_cell), adStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", row_cell), aeStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", row_cell), afStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("H%d", row_cell), agStr)

		arow++
		row_cell++
	}

	err = xlsx.Close()
	if err != nil {
		return 0, 0, err
	}
	err = xlsx.SaveAs(destinationPath)
	if err != nil {
		return 0, 0, err
	}
	return len(listdata), arow, nil
}

func (clockin Clockin) DetailedListExport(row_cell int, page_index int, page_size int, staff string, department string, starttime int, endtime int, ExportId string) (c int, arow int, e error) {
	var err error

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(page_index)-1)*cast.ToInt(page_size), cast.ToInt(page_size))
	orderstr := " order by a.`userid` desc"

	wheresql := strings.Builder{}

	if cast.ToString(staff) != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`name` like '%s'", "%"+cast.ToString(staff)+"%"))
	}

	wheresql.WriteString(fmt.Sprintf(" and b.`relationship` like '%s'", "-1-79%"))

	listsql := fmt.Sprintf("select a.`userid`,a.`name`,a.`position`,c.`employment` from `staff` as a left join department b on a.main_department = b.id left join staff_ext c on a.userid = c.userid where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		return 0, 0, err
	}

	//人员整合
	usermap := []string{}
	//企业微信考勤逻辑处理===========================
	for _, v := range listdata {
		usermap = append(usermap, v["userid"])
	}

	//========================= 开始请求数据
	type ReqCheckinGetcheckinDaydataStruct struct {
		Starttime  int      `json:"starttime"`
		Endtime    int      `json:"endtime"`
		Useridlist []string `json:"useridlist"`
	}
	ReqCheckinGetcheckindata := ReqCheckinGetcheckinDaydataStruct{
		Starttime:  cast.ToInt(starttime),
		Endtime:    cast.ToInt(endtime),
		Useridlist: usermap,
	}

	b, err := json.Marshal(&ReqCheckinGetcheckindata)
	if err != nil {
		return 0, 0, err
	}
	datas, err := utils.CheckinGetcheckinDaydata(b)

	type datemapStruct struct {
		Date             string `json:"date"`
		Weekday          string `json:"weekday"`
		AbsenteeismNotes string `json:"absenteeism_notes"`
		RecordStatus     string `json:"record_status"`
		TestData         string `json:"testdata"`
	}
	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海

	destinationPath := fmt.Sprintf("./DetailedExportTemplate_%s.xlsx", ExportId)
	xlsx, err := excelize.OpenFile(destinationPath)
	if err != nil {
		return 0, 0, err
	}

	arow = 0
	for _, v := range datas.Datas {
		t := time.Unix(cast.ToInt64(v.BaseInfo.Date), 0).In(cstSh)
		datestr := t.Format("2006/01/02")
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("A%d", row_cell), datestr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("B%d", row_cell), v.BaseInfo.Name)

		var positionStr, departmentStr string
		for _, vv := range listdata {
			if vv["userid"] == v.BaseInfo.Acctid {
				positionStr = vv["position"]
				departmentStr = vv["department"]
			}
		}

		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", row_cell), positionStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("D%d", row_cell), departmentStr)
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("E%d", row_cell), v.BaseInfo.RuleInfo.Groupname)

		checktimeStr := ""
		for _, vv := range v.BaseInfo.RuleInfo.Checkintime {
			checktimeStr += clockin.SecondToHours(vv.WorkSec) + "-" + clockin.SecondToHours(vv.OffWorkSec) + "  "
		}
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", row_cell), checktimeStr)
		if checktimeStr == "" && len(v.ExceptionInfos) <= 0 {
			_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", row_cell), "休息")
		}

		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", row_cell), clockin.SecondToHours(v.SummaryInfo.EarliestTime))
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("H%d", row_cell), clockin.SecondToHours(v.SummaryInfo.LastestTime))

		abnormal := ""
		for _, vv := range v.ExceptionInfos {
			//if vv.Exception == 1 {
			//	abnormal += "迟到,"
			//}
			//if vv.Exception == 2 {
			//	abnormal += "早退,"
			//}
			if vv.Exception == 3 {
				abnormal += "缺卡,"
				if v.SummaryInfo.EarliestTime == v.SummaryInfo.LastestTime {
					_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", row_cell), "未打卡")
				}
			}
			if vv.Exception == 4 {
				abnormal += "旷工,"
			}
			//if vv.Exception == 5 {
			//	abnormal += "地点异常,"
			//}
			//if vv.Exception == 6 {
			//	abnormal += "设备异常,"
			//}
		}
		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("I%d", row_cell), abnormal)

		AbsenteeismNotes := ""
		RecordStatus := ""
		//旷工统计
		if (v.BaseInfo.RecordType == 1 || v.BaseInfo.RecordType == 3) && len(v.BaseInfo.RuleInfo.Checkintime) > 0 {
			if v.SummaryInfo.CheckinCount <= 1 {
				for _, vvv := range v.ExceptionInfos {
					if vvv.Exception == 3 || vvv.Exception == 4 {
						RecordStatus = ""
						AbsenteeismNotes = "旷工1天"
					}
				}
			}
			//subtotal := 0
			if v.SummaryInfo.CheckinCount == 2 {

				trunc := math.Trunc(cast.ToFloat64(v.SummaryInfo.EarliestTime) / 60)
				v.SummaryInfo.EarliestTime = cast.ToInt(trunc) * 60

				if v.BaseInfo.RecordType == 1 { //固定
					if v.SummaryInfo.EarliestTime <= v.BaseInfo.RuleInfo.Checkintime[0].WorkSec && v.SummaryInfo.LastestTime >= v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec {
						//正常情况
						RecordStatus = "正常"
						AbsenteeismNotes = ""
					} else if v.SummaryInfo.EarliestTime <= v.BaseInfo.RuleInfo.Checkintime[0].WorkSec+1800 && v.SummaryInfo.LastestTime >= v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec+(v.SummaryInfo.EarliestTime-v.BaseInfo.RuleInfo.Checkintime[0].WorkSec) {
						//弹性正常
						RecordStatus = "正常"
						AbsenteeismNotes = ""
					} else if v.SummaryInfo.EarliestTime > v.BaseInfo.RuleInfo.Checkintime[0].WorkSec+1800 && v.SummaryInfo.LastestTime >= v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec {
						balance := v.SummaryInfo.EarliestTime - v.BaseInfo.RuleInfo.Checkintime[0].WorkSec
						fmt.Println("======================= 固定早上迟到统计")
						fmt.Println("日期：", datestr)
						fmt.Println("balance:", balance)
						fmt.Println("Checkintime[0]：", v.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
						fmt.Println("Checkintime[1]：", v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
						fmt.Println("EarliestTime：", v.SummaryInfo.EarliestTime)
						fmt.Println("LastestTime：", v.SummaryInfo.LastestTime)

						if balance > 0 && balance <= 1800 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5小时"
						} else if balance > 1800 && balance <= 3600 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1小时"
						} else if balance > 3600 && balance <= 5400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1.5小时"
						} else if balance > 5400 && balance < 7200 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工2小时"
						} else if v.SummaryInfo.EarliestTime >= 52200 { //
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						} else if v.SummaryInfo.EarliestTime >= 39600 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5天"
						}
					} else {
						balance := 28800 - v.SummaryInfo.RegularWorkSec
						fmt.Println("======================= 固定迟到统计")
						fmt.Println("日期：", datestr)
						fmt.Println("balance:", balance)
						fmt.Println("Checkintime[0]：", v.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
						fmt.Println("Checkintime[1]：", v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
						fmt.Println("EarliestTime：", v.SummaryInfo.EarliestTime)
						fmt.Println("LastestTime：", v.SummaryInfo.LastestTime)

						if balance > 0 && balance <= 1800 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5小时"
						} else if balance > 1800 && balance <= 3600 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1小时"
						} else if balance > 3600 && balance <= 5400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1.5小时"
						} else if balance > 5400 && balance < 7200 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工2小时"
						} else if balance >= 7200 && balance <= 7200 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5天"
						} else if balance > 7200 && balance < 14400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5天"
						} else if balance >= 14400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					}
				}

				if v.BaseInfo.RecordType == 3 { //排班
					isTrue := false
					for _, vvv := range v.ExceptionInfos {
						if vvv.Exception == 1 || vvv.Exception == 2 {
							isTrue = true
						}
					}
					if v.SummaryInfo.RegularWorkSec < 28800 && isTrue == true { //计算旷工
						balance := 28800 - v.SummaryInfo.RegularWorkSec

						fmt.Println("======================= 排班迟到统计")
						fmt.Println("日期：", datestr)
						fmt.Println("balance:", balance)
						fmt.Println("Checkintime[0]：", v.BaseInfo.RuleInfo.Checkintime[0].WorkSec)
						fmt.Println("Checkintime[1]：", v.BaseInfo.RuleInfo.Checkintime[1].OffWorkSec)
						fmt.Println("EarliestTime：", v.SummaryInfo.EarliestTime)
						fmt.Println("LastestTime：", v.SummaryInfo.LastestTime)

						if balance > 0 && balance <= 1800 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5小时"
						} else if balance > 1800 && balance <= 3600 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1小时"
						} else if balance > 3600 && balance <= 5400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1.5小时"
						} else if balance > 5400 && balance < 7200 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工2小时"
						} else if balance >= 7200 && balance <= 7200 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5天"
						} else if balance > 7200 && balance < 14400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工0.5天"
						} else if balance >= 14400 {
							RecordStatus = ""
							AbsenteeismNotes = "旷工1天"
						}
					} else if isTrue == false {
						RecordStatus = "正常"
						AbsenteeismNotes = ""
					}
				}
			}
		}

		for _, vvv := range v.SpItems {
			if vvv.Type == 1 && vvv.Duration > 0 {
				if RecordStatus == "正常" {
					RecordStatus = ""
				}
				duration := 0.00
				timeType := ""
				if vvv.TimeType == 0 {
					duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(86400)
					timeType = "天"
				} else if vvv.TimeType == 1 {
					duration = cast.ToFloat64(vvv.Duration) / cast.ToFloat64(3600)
					timeType = "小时"
				}
				RecordStatus += fmt.Sprintf("%s%.2f%s ", vvv.Name, cast.ToFloat64(duration), timeType)
			}
			if vvv.Type == 2 && vvv.Count > 0 {
				RecordStatus = fmt.Sprintf("补卡")
			}
			if vvv.Type == 3 && vvv.Count > 0 {
				RecordStatus = fmt.Sprintf("%s", vvv.Name)
			}
			if vvv.Type == 4 && vvv.Count > 0 {
				RecordStatus = fmt.Sprintf("%s", vvv.Name)
			}
			if vvv.Type == 100 && vvv.Count > 0 {
				RecordStatus += fmt.Sprintf("%s", vvv.Name)
			}
		}

		spTotal := 0
		for _, vvv := range v.SpItems {
			if vvv.Type == 1 && vvv.Duration > 0 {
				spTotal += vvv.Duration
			}
		}
		if spTotal > 0 && spTotal < 28800 {
			fmt.Println("======================= 请假统计")
			fmt.Println("日期：", datestr)
			fmt.Println("spTotal:", spTotal)
			RecordStatus += fmt.Sprintf("出勤%.2f小时", cast.ToFloat64(v.SummaryInfo.RegularWorkSec)/3600)
		}
		if v.SummaryInfo.RegularWorkSec+spTotal > 28800 {
			AbsenteeismNotes = ""
		}

		_ = xlsx.SetCellValue("Sheet1", fmt.Sprintf("J%d", row_cell), AbsenteeismNotes)

		arow++
		row_cell++
	}

	err = xlsx.Close()
	if err != nil {
		return 0, 0, err
	}
	err = xlsx.SaveAs(destinationPath)
	if err != nil {
		return 0, 0, err
	}
	return len(listdata), arow, nil
}

func (clockin Clockin) SecondToHours(second int) string {
	//cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海
	nowtime := time.Now().Truncate(24 * time.Hour).Unix()
	newunix := nowtime + cast.ToInt64(second)
	t := time.Unix(newunix, 0)
	// 格式化时间为字符串
	str := t.Format("15:04")
	//pi := cast.ToFloat64(second) / 3600
	//s1 := fmt.Sprintf("%.2f", pi)
	return str
}

func weekDayString(u int) string {
	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海
	timestamp := int64(u)                          // 设置要查询的时间戳（此处为2020年8月20日）
	t := time.Unix(timestamp, 0).In(cstSh)         // 将时间戳转换为本地时区的时间
	weekDay := t.Weekday()                         // 获取星期几信息
	switch weekDay {
	case time.Sunday:
		return "星期天"
	case time.Monday:
		return "星期一"
	case time.Tuesday:
		return "星期二"
	case time.Wednesday:
		return "星期三"
	case time.Thursday:
		return "星期四"
	case time.Friday:
		return "星期五"
	case time.Saturday:
		return "星期六"
	}
	return ""
}

func formatDuration(seconds int64) string {
	const (
		minute = 60
		hour   = 60 * minute
		day    = 24 * hour
	)
	days := seconds / day
	seconds -= days * day
	hours := seconds / hour
	seconds -= hours * hour
	minutes := seconds / minute
	seconds -= minutes * minute
	var buf bytes.Buffer
	if days > 0 {
		fmt.Fprintf(&buf, "%d天", days)
	}
	if hours > 0 || (days > 0 && (minutes > 0 || seconds > 0)) {
		fmt.Fprintf(&buf, "%d小时", hours)
	}
	if minutes > 0 || (hours > 0 && seconds > 0) {
		fmt.Fprintf(&buf, "%d分钟", minutes)
	}
	if seconds >= 0 || (days == 0 && hours == 0 && minutes == 0) {
		fmt.Fprintf(&buf, "%d秒", seconds)
	}
	return buf.String()
}

func (clockin Clockin) IsTimeCross(data [][]int) (r bool, num int) {
	n := 0

	if len(data) == 1 {
		return true, 0
	}

	for i := 1; i < len(data); i++ {
		pre := data[i-1]
		current := data[i]
		if pre[0] <= current[1] && current[0] <= pre[1] {
			return true, 0
		} else {
			n += current[0] - pre[1]
		}
	}
	return false, n
}

func (clockin Clockin) RepairAdd(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	datainsert := make(map[string]interface{})
	datainsert["userid"] = cast.ToString(jsondata["userid"])
	datainsert["date"] = cast.ToInt(jsondata["date"])
	datainsert["note"] = cast.ToString(jsondata["note"])
	datainsert["ctime"] = time.Now().Unix()
	_, err = db.Table("repair").Insert(datainsert)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

func (clockin Clockin) RepairList(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), cast.ToInt(jsondata["page_size"]))
	orderstr := " order by a.`ctime` asc"

	wheresql := strings.Builder{}

	if jsondata["starttime"] != "" && jsondata["endtime"] != "" {
		wheresql.WriteString(fmt.Sprintf(" and a.`date` >= %s AND a.`date` <= %s", cast.ToString(jsondata["starttime"]), cast.ToString(jsondata["endtime"])))
	}
	wheresql.WriteString(fmt.Sprintf(" and a.`userid` = '%s'", cast.ToString(jsondata["userid"])))

	listsql := fmt.Sprintf("select a.`userid`,FROM_UNIXTIME(a.`date`) as date,a.`note`,FROM_UNIXTIME(a.`ctime`) as ctime from `repair` as a where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	countsql := fmt.Sprintf("select count(*) as total from `repair` as a where 1=1 %s", wheresql.String())
	countdata, err := db.QueryString(countsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	service.ReturnJson(c, 200, "操作成功", gin.H{
		"list":  listdata,
		"total": cast.ToInt(countdata[0]["total"]),
	})
}
